我正在尝试围绕无符号整数和有符号整数设计编号系统.这两种类型都有一个underlying
值,表示Scala数字系统中的数字.这是我到目前为止的类型层次结构.
sealed trait Number {
def + (num : Number) : Number = ???
def - (num : Number) : Number = ???
def * (num : Number) : Number = ???
}
sealed trait SignedNumber extends Number
sealed trait UnsignedNumber extends Number
sealed trait UInt32 extends UnsignedNumber {
def underlying : Long
}
sealed trait UInt64 extends UnsignedNumber {
def underlying : BigInt
}
sealed trait Int32 extends SignedNumber {
def underlying : Int
}
sealed trait Int64 extends SignedNumber {
def underlying : Long
}
Run Code Online (Sandbox Code Playgroud)
我想underlying
在特征中定义,Number
以便编译器可以强制执行underlying
在所有子节点中定义的.但是,underlying
每种特性的类型各不相同 - 我希望为每种类型保留尽可能小的类型.例如,a UInt32
可以存储为long
Scala中,而a UInt64
需要存储为BigInt
.
这样做最有效的方法是什么?
type
您可以在父特征中声明 a并在子特征中覆盖它。
sealed trait Number {
type A
def underlying: A
def + (num : Number) : Number = ???
def - (num : Number) : Number = ???
def * (num : Number) : Number = ???
}
sealed trait SignedNumber extends Number
sealed trait UnsignedNumber extends Number
sealed trait UInt32 extends UnsignedNumber {
override type A = Long
}
sealed trait UInt64 extends UnsignedNumber {
override type A = BigInt
}
sealed trait Int32 extends SignedNumber {
override type A = Int
}
sealed trait Int64 extends SignedNumber {
override type A = Long
}
Run Code Online (Sandbox Code Playgroud)
一个示例只是为了在不清楚的情况下展示路径相关类型的使用:
def getUnderlying(x: Number): x.A = x.underlying
Run Code Online (Sandbox Code Playgroud)
为了获得正确的返回类型,我认为type
可能需要另一个。
sealed trait Number {
type A
type B
def underlying: A
def +(that: B): B
}
sealed trait UInt32 extends Number { x =>
override type A = Long
override type B = UInt32
override def +(y: B): B = new UInt32 {
// todo - naive implementation, doesn't check overflow
override val underlying = x.underlying + y.underlying
}
}
def main(args: Array[String]) {
print((
new UInt32 { def underlying = 3 } +
new UInt32 { def underlying = 4 }
).underlying)
}
Run Code Online (Sandbox Code Playgroud)