如何在多态性中辅助类型推断?

时间:2015-08-13 18:15:22

标签: scala

旧标题:您如何显示或声明列表是TraversableOnce?

我一直试图为某些课程设计一个特质。在这个特性中,我尝试了以下任何一个:

  //First try:
  def addData[A <: Any](newTweets: => List[A]): Unit
  //Second try
  def addData[A <: List[Any]](newTweets: => A): Unit
  //Third try
  def addData[A <: List[Any]](newTweets: => A): Unit

我有几个不同的实现,例如:

  def addData[Future[JsValue]](newData: => List[Future[JsValue]]): Unit = {
    dataList ++= newData
  }

  def addData[Tweet](newTweets: => List[Tweet]): Unit = {
    tweetsList ++= newTweets
    tweetsList = tweetsList.sortWith(
      (a,b) => a.created_at.getTime < b.created_at.getTime
    )

我在IntelliJ和编译器断言如下所示的错误:

JsonPublisher.scala:23: error: type mismatch;
 found   : List[Future[play.api.libs.json.JsValue]]
 required: scala.collection.TraversableOnce[scala.concurrent.Future[play.api.libs.json.JsValue]]
    dataList ++= newData

我最困惑的部分是我相信List应该实现TransversableOnce。此外,在使类从自定义特征扩展之前,这工作正常。唯一的区别是我没有在类中参数化方法的类型,例如,我有def addData(...而不是addData[Tweet](...。但是,如果我离开,我不会在从特征延伸时更改要参数化的函数形式,我会收到一条投诉,说明我没有实现addData

我欢迎两种新的方法和提示,说明为什么会出现这种错误(因为List应该是TransversableOnce)。

修改

在忘记列表并制作所有内容TransversableOnce之后,我仍然会得到一个可能相同的错误,但可能更有启发性(只是对我而言):

[ant:scalac] /home/brandon/CommVis/jvm-scala/tweet-serve/src/main/scala/edu/cornell/comm/twitter/JsonPublisher.scala:23: error: type mismatch;
[ant:scalac]  found   : TraversableOnce[Future[play.api.libs.json.JsValue]]
[ant:scalac]  required: scala.collection.TraversableOnce[scala.concurrent.Future[play.api.libs.json.JsValue]]
[ant:scalac]     dataList ++= newData
[ant:scalac]                  ^
[ant:scalac] /home/brandon/CommVis/jvm-scala/tweet-serve/src/main/scala/edu/cornell/comm/twitter/TweetPublisher.scala:38: error: type mismatch;
[ant:scalac]  found   : scala.collection.TraversableOnce[Tweet]
[ant:scalac]  required: scala.collection.TraversableOnce[edu.cornell.comm.twitter.Tweet]
[ant:scalac]     tweetsList ++= newTweets

我还会包含更完整的代码:

性状

package edu.cornell.comm.api

import scala.collection.{TraversableOnce}
import scala.collection.mutable.{MutableList, Publisher}
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent._
import edu.cornell.comm.twitter.types.Tweet
import scala.collection.mutable.{Publisher}

trait MicroBlogPublisher[T] extends Publisher[Future[String]] {

  def addData[T](newTweets: => TraversableOnce[T]): Unit

}

实施一

package edu.cornell.comm.twitter

import edu.cornell.comm.api.MicroBlogPublisher
import edu.cornell.comm.twitter.types.IOHelpers._
import edu.cornell.comm.twitter.types._
import play.api.libs.json.{JsValue, Json}
import scala.collection.mutable.{MutableList, Publisher}
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent._

class JsonPublisher extends MicroBlogPublisher[Future[JsValue]] {

  protected var dataList: MutableList[Future[JsValue]] = MutableList.empty

  def addData[Future[JsValue]](newData: => TraversableOnce[Future[JsValue]]): Unit = {
    dataList ++= newData
  }


}

实施二

package edu.cornell.comm.twitter

import edu.cornell.comm.api.MicroBlogPublisher
import play.api.libs.json.Json
import scala.collection.{TraversableOnce}
import scala.collection.mutable.{MutableList, Publisher}
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent._
import edu.cornell.comm.twitter.types._
import IOHelpers._

class TweetPublisher extends MicroBlogPublisher[Tweet] {


  protected var tweetsList: MutableList[Tweet] = MutableList.empty


  def addData[Tweet](newTweets: => TraversableOnce[Tweet]): Unit = {
    tweetsList ++= newTweets
    tweetsList = tweetsList.sortWith(
      (a,b) => a.created_at.getTime < b.created_at.getTime
    )
  }


}

1 个答案:

答案 0 :(得分:2)

你很有趣。

这是正确的代码:

addData

问题是方法T声明了自己的泛型类型T,它与特征的类型参数JsonPublisher完全无关。现在有趣的部分,在具体实现中,例如def addData[Future[JsValue]](...,声明Future实际上声明了两个具有混淆名称JsValuedef addData[P[Q]](...的泛型类型参数。但实际上这个声明是def addData[T]的同义词。

现在你可以避免这个错误。

对我来说,Idea会在MicroBlogPublisher中声明T声明:&#34;类型参数T&#34;的可疑阴影。应该已经指出override现在看起来像是什么。接下来,当你重写方法时,不要忘记var app = express(); var server = app.listen(8080); var io = require('socket.io').listen(server); 关键字。当重写方法的签名出现问题时,您将被告知。