为了确保协方差,有三种方法:
- 纯协方差:使用埃菲尔语言,
- 模拟协方差:使用强制转换和重载
- 使用 F 有界多态或虚类型
因此,我正在使用虚拟类型测试解决方案,在以下示例中使用 scala Abstract 类型:
- 我们定义了 3 个抽象类:Graph、Node、Edge
- Graph 类定义了 2 个方法:attachNode(Node) 和 detachNode(Node)
- Node 类定义了 2 个方法:attachToGraph(Graph) 和 detachFromGraph()
使用 inheretence 我们将为不同的域创建不同的子类:
- 对于网络 :
class Network extends Graph
, 和class Host extends Node
, .. - 对于化学:
class Molecule extends Graph
, 和class Atom extends Node
,.. - ...
唯一的限制是通过例如将 Atom 附加到网络来避免创建“嵌合体”。所以模型比较简单:
abstract class Graph {
type CompatibleNode <: Node
protected var myNodes = new ArrayBuffer[CompatibleNode]()
def attachNode(node : compatibleNode) = {
....
// Inform the node about the attachement so it can do update
node.attachToGraph(this)
// save the node
myNodes += node
}
}
abstract class Node {
type CompatibleGraph >: scala.Null <: Graph
protected var myGraph : CompatibleGraph = null
def attachToGraph(graph : compatibleGraph) = {
....
// Inform the graph about the attachement so it can do update
graph.attachNode(this)
// save the node
myGraph = graph
}
}
在创建特殊图表之后,我们只需覆盖虚拟类型:
class Network extends Graph { override type CompatibleNode = Host}
class Host extends Node { override type CompatibleGraph = Network}
class Molecule extends Graph { override type CompatibleNode = Atom}
class Atom extends Node { override type CompatibleGraph = Molecule}
这应该工作得很好(它在 NIT 语言中工作)但我有不同的错误:
首先,在调用
graph.attachNode(this)
这个时输入不匹配graph.CompatibleNode
,找到:Graph
,所以我投了这个:graph.attachNode(this.asInstanceOf[graph.CompatibleNode])
请注意,NIT 语言会隐式进行强制转换。
其次,在 detachFromGraph() 方法之后:
类节点{
... def detachFromGraph() = { .... // inform my graph myGraph.detachNode(this.asInstanceOf[myGraph.CompatibleNode]) ... }
}
我得到了错误:myGraph.compatibleNode : requiered stable identifier
,在搜索和阅读规范后,我发现:->一个稳定的标识符是以标识符结尾的路径->p.x
是一个路径,如果p
是一个路径并且x
是一个稳定的成员->稳定的成员是.. ...或非易失性类型的值定义 -> 易失性类型:类型参数或抽象类型,...。
所以简而言之,我不能在路径中使用抽象类型的对象,为什么?我不知道!
所以如果有人有建议,或者即使可以使用 scala 抽象类型作为虚拟类型。