我定义了以下类,PositionSpace,它有嵌套类Position和SubPositionSpace。 SubPositionSpace本身既是Position又是PositionSpace(因此它也是一个定义了自己位置的位置)。我已经定义了一个包装类SubPosition,因此任何类型为x.SubPositionSpace#Position的对象(对于任何作为PositionSpace的对象x)都可以用作x.Position类型的对象。但是,我想隐含这种转换,这就是我被困住的地方。从逻辑上讲,它应该是可能的。但是,我无法弄清楚在何处或如何定义转换,以便编译器找到它,并且它让我头疼。
以下是我的代码。请注意,我已将测试用例添加到底部。
class PositionSpace { positionSpace =>
//snip
trait Position extends Ordered[Position] {
//snip
}
class SubPositionSpace() extends PositionSpace with Position { subPositionSpace =>
//snip
//wrapper class to treat a x.SubPositionSpace#Position as a x.Position for some x : PositionSpace
//want to make this conversion implicit!!!
class SubPosition(private val subPositionIndex : subPositionSpace.Position) extends positionSpace.Position {
//snip
}
}
def append() = new Position{
//snip
}
def appendSubSpace() = new SubPositionSpace()
}
object TestCases {
val positionSpace = new PositionSpace()
val subSpace = positionSpace.appendSubSpace()
val subSpacePosition = subSpace.append()
//Does not compile, needs an implicit conversion:
val subSpacePositionAsPosition : positionSpace.Position = subSpacePosition
val subSubSpace = subSpace.appendSubSpace()
//Does not compile, needs an implicit conversion:
val subSubSpacePositionAsPosition : positionSpace.Position = subSubSpace
}
与路径相关的类型
部分问题似乎是此转换涉及路径相关类型,其中输入类型和输出类型使用相同的路径。但是,没有语法来编写具有类型x.Position => y.Position where y : PositionSpace and x : y.SubPositionSpace.
的签名的方法。通过添加额外的参数来传递路径(如下所示)可以很容易地解决问题,但是您无法添加其他参数隐式转换方法(如果您希望它们可以这样使用)。
//Too many arguments, won't be used by compiler for implicit conversions
implicit def promotePosition(y : PositionSpace, x : y.PositionSpace, x.Position) : y.Position = ...
答案 0 :(得分:1)
这是我想出的部分答案并开始工作。基本上,您创建一个空特征SubPositionSpacePosition,它应用于所有2级位置。然后,您可以为SubPositionSpacePosition定义一个定义隐式转换的伴随对象。您只能将leve-2位置的转换定义为level-1位置。除此之外的任何事情,你都遇到了我在问题中概述的障碍。
import scala.language.implicitConversions
class PositionSpace { positionSpace =>
trait Position extends Ordered[Position] {
}
trait SubPositionSpace extends PositionSpace with Position { subPositionSpace =>
trait SubPositionSpacePosition extends subPositionSpace.Position {
}
def append() = new Position with SubPositionSpacePosition { }
def appendSubSpace() = new SubPositionSpace with SubPositionSpacePosition { }
class SubPosition(private val subPositionIndex : subPositionSpace.Position) extends positionSpace.Position {
}
object SubPositionSpacePosition {
implicit def promoteSubPositionSpacePosition(subPositionSpacePosition : SubPositionSpacePosition) : positionSpace.Position =
new SubPosition(subPositionSpacePosition)
}
}
def append() = new Position { }
def appendSubSpace() = new SubPositionSpace { }
}
object TestCases {
val positionSpace = new PositionSpace()
val subSpace = positionSpace.appendSubSpace()
val subSpacePosition = subSpace.append()
val subSpacePositionAsPosition : positionSpace.Position = subSpacePosition
val subSubSpace = subSpace.appendSubSpace()
val subSubSpacePosition = subSubSpace.append()
//this still fails to build!!!
val subSubSpacePositionAsPosition : positionSpace.Position = subSubSpacePosition
}
答案 1 :(得分:0)
我认为你不想在这里进行隐式转换 - 仅仅为类型系统提供跟踪路径依赖类型所需的信息会更加清晰。实现此目的的一种方法是抽象出将类型联系在一起的骨架:
trait PSpace { pSpace =>
type P
type Sub <: P with PSpace {
type P = pSpace.P
type Sub = pSpace.Sub
}
def append(): P
def appendSubSpace(): Sub
}
您也可以使用类型参数,但我猜测类型成员会更好用于您的用例。然后你提供你的实现:
class PositionSpace { positionSpace =>
type P = Position
type Sub = SubPositionSpace
trait Position
class SubPositionSpace() extends PSpace with Position {
type P = positionSpace.P
type Sub = positionSpace.Sub
class SubPosition(private val subPositionIndex: P) extends P
def append() = new Position {}
def appendSubSpace() = new SubPositionSpace()
}
def append() = new Position {}
def appendSubSpace() = new SubPositionSpace()
}
现在,测试代码的所有行都可以正常编译。