【问题标题】:Good ways to create a Scala class whose Type parameter depends on composing object Type创建类型参数取决于组合对象类型的 Scala 类的好方法
【发布时间】:2013-04-23 04:57:51
【问题描述】:

我正在磨练我的 scala 技能,并且正在编写一些图形算法。我有一个类似这样的图形 API 表示

trait GraphLike[T]
{
  val vertices: Map[ T, VertexLike[T] ] 
  def addVertex( t: T ): GraphLike[T]
  def addEdge( a:T, b:T ): GraphLike[T]
  def getAdjacencyList( a: T ): List[T]
  def getVertex( a: T ): VertexLike[T]
  ...
}

然后我有另一个课:

class DepthFirstSearch[ T ]( val graph: GraphLike[T], val sourceVertex: T )
{
  ...
}

目前我发现我必须这样做才能创建 DepthFirstSearch 类的实例

val dfs = new DepthFirstSearch[Integer]( new UnDirGraph[Integer](/*some params*/), 1 )

其中UnDirGraphGraphLike 子类

我必须在new DepthFirstSearch[Integer] 中指定类型参数。有没有一种方法可以让类型检查器从提供的图形参数中推断出来。我发现我做不到 做这样的事情

val dfs = new DepthFirstSearch( new UnDirGraph[Integer](/*some params*/), 1 )

目前上述方法失败...有没有办法可以完成上述操作?

编辑:所以我得到的错误信息是 类型不匹配;发现:com.KGraph.GraphLike[Integer]
必需:com.KGraph.GraphLike[任何] 注意:Integer <: any graphlike trait t>

这就是我尝试创建的方式

val graph = Graphing.createUndiGraphFromFile( 
            new File("/Volumes/Data/Users/kartik/ScalaSpace/Graph/tinyG.txt" ) )
val dfs = new DepthFirstSearch( graph, 0 )

crateUndiGraphFromFile 返回一个 GraphLike[Integer]

【问题讨论】:

  • 多一点信息会很好。例如错误信息是什么?
  • 它推断类型/强制T的一致绑定,但它不会自动查找和调用构造函数。你可以使用反射来做到这一点。你必须得到一个ClassTag(如果你问,编译器会为你做这件事)然后陷入反射。而且由于您需要默认(无参数)构造函数以外的其他东西,因此对于默认构造函数来说,它会更加新颖。我知道 Java 反射可以用于这类事情(我已经做过),但我不熟悉该领域的 2.10 Scala 反射功能。那样有可能不那么丑。
  • @Kartik Aiyer:现在没有时间给出正确的答案,但你应该知道Integer 指的是java.lang.Integer,而不是原始的scala.Int。将Integer 更改为Int 可能会解决您的问题(我在repl 中快速尝试过,Integer 出现差异错误,但Int 没有出现差异错误)。 @Randall Schulz:我认为你误解了这个问题,不知何故。
  • 展开,文字1scala.Int,而不是java.lang.Integer。因此,common 类型,并且仅适用于T 的推断是Any。但是如果T 解析为Any,这意味着您将分配一个UnDirGraph[Int] 给一个不允许的GraphLike[Any],因为T 不是协变的(它是invariant )。因此编译器建议使用+T 而不是T。对我来说真正有趣的部分是,一旦你添加了[Integer],它就可以工作,这表明1可以在强制时自动转换为java.lang.Integer,这是我还不知道的。
  • @MarkPeters 1 被转换为java.lang.Integer 是常见的拳击。在 Scala 中,Predef.int2Integer 负责处理这个问题。

标签: scala


【解决方案1】:

感谢@Régis Jean-Gilles 和@Mark Peters

Integer1Int 类型)的共同超类型是 Any。所以在写这个的时候:

val dfs = new DepthFirstSearch( new UnDirGraph[Integer](/*some params*/), 1 )

类型推断给你

val dfs = new DepthFirstSearch[Any]( new UnDirGraph[Integer](/*some params*/), 1 )

但是现在,我们需要

new UnDirGraph[Integer](/*some params*/) <: UniDirGraph[Any]

情况并非如此,因为UnDirGraph 是不变的。

如果你写:

val dfs = new DepthFirstSearch[Integer]( new UnDirGraph[Integer](/*some params*/), 1 )

Scala 会将1 隐式转换为Integer,然后一切正常。

正如@Régis Jean-Gilles 指出的那样,以下方法将起作用:

val dfs = new DepthFirstSearch( new UnDirGraph[Int](/*some params*/), 1 )

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-12-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-19
    • 1970-01-01
    • 2020-02-08
    • 2011-09-29
    相关资源
    最近更新 更多