[英]Scala Type Aliases and Method Overloading
我正在写一些Scala,它处理线性时间线上的间隔。 当前interval的开始和结束都表示为Int
,但是,在某些情况下,我想将它们稍作不同(但是为了处理某些外部代码,它们仍需要为Int
)。
我认为这是一种类型别名将是添加一些编译时检查的好方法,并且我可以通过方法重载来处理不同的处理的情况。 这是一个说明性的示例:
type IntervalStart = Int
type IntervalEnd = Int
case class Interval(s: IntervalStart, e: IntervalEnd)
val i = Interval(1, 10)
def process(s: IntervalStart): Unit = { println("Do some start specific work") }
def process(e: IntervalEnd): Unit { println("Do some end specific work") }
process(i.s) // "Do some end specific work" WRONG!!
process(i.e) // "Do some end specific work"
似乎它没有适当地使process
方法过载,并且总是选择后面的定义。 这是Scala类型别名的限制,某些怪异的JVM类型擦除内容还是对我自己的正确行为的误解?
类型别名只是一个别名,它不会改变类型本身。 IntervalStart
和IntervalEnd
仍然是Int
,因此process(s: IntervalStart)
和process(e: IntervalEnd)
具有相同的签名,这是非法的。
您可以这样声明它们:
case class IntervalStart(i: Int)
case class IntervalEnd(i: Int)
def process(s: IntervalStart): Unit = ...
def process(e: IntervalEnd): Unit = ...
但是然后您必须创建实际的IntervalStart
和IntervalEnd
对象才能传递。 如果这两个功能将做不同的事情,我认为您应该以不同的方式命名它们。
def processStart(s: Int): Unit = ...
def processEnd(e: Int): Unit = ...
两种process
方法擦除为同一方法,这是一个错误:
Welcome to Scala version 2.11.2 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_20).
Type in expressions to have them evaluated.
Type :help for more information.
scala> :pa
// Entering paste mode (ctrl-D to finish)
type IntervalStart = Int
type IntervalEnd = Int
def process(s: IntervalStart): Unit = { println("Do some start specific work") }
def process(e: IntervalEnd): Unit = { println("Do some end specific work") }
// Exiting paste mode, now interpreting.
<console>:11: error: method process is defined twice
conflicting symbols both originated in file '<console>'
def process(e: IntervalEnd): Unit = { println("Do some end specific work") }
^
您可能在REPL中通过连续声明它们的方法来测试了它们的方法(但不是一起声明),所以您没有收到错误,第二个方法只是遮盖了第一个方法(这就是REPL使您能够“重新定义”范围内的某些方法的方法) )。
那不是您要查找的别名:
package object tagged {
type Tagged[U] = { type Tag = U }
type @@[T, U] = T with Tagged[U]
}
package tagged {
trait Start
object Start {
def apply(i: Int): Int @@ Start = i.asInstanceOf[Int @@ Start]
}
trait End
object End {
def apply(i: Int): Int @@ End = i.asInstanceOf[Int @@ End]
}
case class Interval(start: Int @@ Start, end: Int @@ End)
object P {
def p(i: Int @@ Start) = s"Start at $i"
def p(i: Int @@ End)(implicit d: DummyImplicit) = s"End at $i"
}
object Test extends App {
Console println (P p Start(9))
Console println (P p End(5))
val x = Interval(Start(9), End(5))
Console println (P p x.start)
Console println (P p x.end)
}
}
DummyImplicit是消除运行时签名歧义的方法。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.