简体   繁体   English

涉及重写方法的使用,类型边界和…类型擦除

[英]involved usage of overridden methods, type bounds, and… type erasure

This is really an involved scenario. 这确实是一个涉及的场景。 Vertices and edges are added to a graph. 顶点和边添加到图中。 A convenience method for adding a variable amount of them has been desired. 需要一种方便的方法来添加可变数量的它们。 Any way I try to make the latter api requirement happen I fail over type erasure, or a compiler failure to resolve which overridden method needs to be called. 我尝试使后一种api要求发生的任何方式,都会使我无法进行类型擦除,或​​者无法解决需要调用哪个重写方法的编译器故障。 Here's the code intent expressed through one failed variation: 这是通过一种失败的变体形式表达的代码意图:

/*
 * API definition
 */
abstract class AbstractGraph[ID, Vertex <: AbstractVertex[ID], Edge <: AbstractEdge[ID]]  {

  def += (vertex: Vertex): AbstractGraph[ID, Vertex, Edge] 

  def += (edge: Edge): AbstractGraph[ID, Vertex, Edge] 

  def ++=(inputs: Addable*): AbstractGraph[ID, Vertex, Edge] = {
    inputs.foreach(i => i match {
      case v : AbstractVertex[ID] => this += v
      case e : AbstractEdge[ID]   => this += e
    })
    this
  } 
}


abstract trait Addable

/*
 * trait to be mixed in by user code for making their nodes graph friendly
 */
abstract trait AbstractVertex[ID] extends Addable {  
  val id: ID 
} 

/*
 * trait to be mixed in by user code for making their edges graph friendly
*/
abstract trait AbstractEdge[ID] extends Addable {
  val id1: ID
  val id2: ID
}

This intent demonstrating variation above, fails with the following: 上面显示此意图的变体由于以下原因而失败:

overloaded method value += with alternatives:
(edge: Edge)org.canve.simpleGraph.AbstractGraph[ID,Vertex,Edge] <and>
(vertex: Vertex)org.canve.simpleGraph.AbstractGraph[ID,Vertex,Edge]
cannot be applied to (org.canve.simpleGraph.AbstractVertex[ID])
  case v : AbstractVertex[ID] => this += v
                                      ^

overloaded method value += with alternatives:
(edge: Edge)org.canve.simpleGraph.AbstractGraph[ID,Vertex,Edge] <and> (vertex: Vertex)org.canve.simpleGraph.AbstractGraph[ID,Vertex,Edge]
cannot be applied to (org.canve.simpleGraph.AbstractEdge[ID])
  case e : AbstractEdge[ID]   => this += e
                                      ^

Believe me this has been my most elegant attempt... even though it was silly to assume the compiler would infer the appropriate overloaded += method from the type bound of its signature's argument type. 相信我,这是我最优雅的尝试……尽管愚蠢地认为编译器会从其签名的参数类型的类型边界中推断出适当的重载+=方法。 Practically every other variation I try hits a type erasure wall in some place. 实际上,我尝试的所有其他变体都会在某个地方碰到类型擦除墙。

Can you suggest a way to implement the ++= method after all? 毕竟,您能建议一种实现++=方法的方法吗?

Oddly enough a similarly titled question also came from the realm of graphs ;( 奇怪的是,一个类似标题的问题也来自图的领域;(

Call me obsessive but not being able to materialize this api is really disappointing so I'd appreciate your help and insight. 称我为痴迷者,但无法实现此api确实令人失望,因此,感谢您的帮助和见解。 Of course I could split ++= to a vertices only method and an edges only method, but that alone will... type erasure fail. 当然,我可以将++ =拆分为仅顶点方法和仅边方法,但仅此而已...类型擦除失败。 I could go with different names as well and that might lead the way to fallback from this clean api design - but that excludes providing an elegant api to my library. 我也可以使用不同的名称,这可能会导致从这种简洁的api设计回退的方式-但不包括为我的库提供优雅的api。

I think I can get past the type erasure problem I refer to in my comment using implicit ClassTags: 我认为我可以使用隐式ClassTag克服我在评论中提到的类型擦除问题:

// Add implicit ClassTag references to AbstractGraph types:
abstract class AbstractGraph[ID, Vertex <: AbstractVertex[ID] : ClassTag, Edge <: AbstractEdge[ID] : ClassTag]  {

  def += (vertex: Vertex): AbstractGraph[ID, Vertex, Edge] 

  def += (edge: Edge): AbstractGraph[ID, Vertex, Edge] 

  def ++= (inputs: Addable*): AbstractGraph[ID, Vertex, Edge] = {
    inputs.foreach(i => i match {
      case v : Vertex => this += v
      case e : Edge   => this += e
    })
    this
  } 
}

// ... rest as before

I seem to have solved it on top my posted code, by using coercion as follows, but will check all the above comments for other simplifications and possibilities. 通过使用强制,我似乎已经在我发布的代码之上解决了该问题,但是将检查以上所有注释,以获取其他简化和可能性。

case v : AbstractVertex[ID] => += (v.asInstanceOf[Vertex])
case e : AbstractEdge[ID]   => += (e.asInstanceOf[Edge])

Comments about this kind of solution are of course most welcome. 当然欢迎对这种解决方案发表评论。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM