【发布时间】:2013-05-21 01:35:34
【问题描述】:
为了保证协方差,有三种方法:
- 纯协方差:使用埃菲尔语言,
- 模拟协方差:使用强制转换和重载
- 使用 F 有界多态或虚类型
所以我正在使用虚拟类型测试解决方案,在以下示例中使用 scala 抽象类型:
- 我们定义了 3 个抽象类:Graph、Node、Edge
- Graph 类定义了 2 个方法:attachNode(Node) 和 detachNode(Node)
- Node 类定义了 2 个方法:attachToGraph(Graph) 和 detachFromGraph()
使用继承我们将为不同的域创建不同的子类:
- 对于网络:
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 是稳定成员
-> 稳定成员是.....或非易失类型的值定义
-> volatile types:类型参数或抽象类型,....
简而言之,我不能在 path 中使用抽象类型的对象,为什么?我不知道!
所以如果有人有建议,或者即使可以使用 scala 抽象类型作为虚拟类型。
【问题讨论】:
-
我不明白 Eiffel 如何“确保”协方差。它处理协方差的方式甚至违反了 Liskov 替换原则,允许协变类型参数,即使它们处于逆变位置。
-
我在 this question 的 cmets 中读到(我有类似的问题),可以在 C++ 中实现其中的一些想法。有人知道怎么做吗?
-
你在说什么样的协方差?如果你能说出你的定义,也许会有所帮助。目前你的定义是不健全的,因为如果你调用
attachNode,你不能确保this与Node兼容(和v.v.为attachToGraph),因为你的类型方案不需要/表达这种兼容性关系是对称的。
标签: scala covariance abstract-type