[英]scala trait or abstract type or parameter type or what?
I wish to use several classes interchangeably, all of them implementing a method "add", so I start to write a trait: 我希望交替使用几个类,所有这些类都实现了一个方法“add”,所以我开始写一个特性:
trait CanAdd{
def add(that: CanAdd): CanAdd
}
then implement my classes and hit a problem: I cannot add any "CanAdd" with any other, they need to be of the same class. 然后实现我的类并遇到问题:我不能添加任何其他“CanAdd”,它们需要属于同一个类。 I workaround the problem with some ugly code relying on "isInstanceOf":
我用一些依赖于“isInstanceOf”的丑陋代码解决了这个问题:
class A(val value: Int) extends CanAdd{
def add(that: CanAdd): CanAdd = {
if(!that.isInstanceOf[A]) sys.error("")
val thatA: A = that.asInstanceOf[A]
new A(value + thatA.value)
}
}
class B(val value: Boolean) extends CanAdd{
def add(that: CanAdd): CanAdd = {
if(!that.isInstanceOf[B]) sys.error("")
val thatB: B = that.asInstanceOf[B]
new B(value ^ thatB.value)
}
}
Finally, I use the classes as follow: 最后,我使用如下类:
class User(val stuff: Array[CanAdd]) {
def add(that: User): User = {
assume(stuff.length==that.stuff.length)
val out = new Array[CanAdd](stuff.length)
for( i <- 0 until stuff.length) out(i) = stuff(i).add(that.stuff(i))
new User(out)
}
}
val u1=new User(Array(new A(0)))
val u2=new User(Array(new B(false)))
val u3 = u1.add(u1)
val u4 = u1.add(u2) //should fail, ideally, should not even compile
I don't like it because first it is a burden to write the boiler plate code with "isInstanceOf" and second because it fails at run time instead of compile time. 我不喜欢它,因为首先用“isInstanceOf”写锅炉板代码是一种负担,其次是因为它在运行时而不是编译时失败。
My question: how would you do that, having in mind some plan to implement many more methods than just "add" and maybe to implement few other classes with very different internal representations ? 我的问题:你会如何做到这一点,考虑到一些计划实现更多的方法,而不仅仅是“添加”,并可能实现几个具有非常不同的内部表示的其他类?
trait CanAdd[T <: CanAdd[T]] {
def add(a: T): T
}
class A(val value:Int) extends CanAdd[A] {
def add(that:A) = new A(value+that.value)
}
class B(val value:Boolean) extends CanAdd[B] {
def add(that:B) = new B(value ^ that.value)
}
class User[X <: CanAdd[X] : Manifest](val stuff:Array[X]) extends CanAdd[User[X]]{
def add(that:User[X]):User[X] = {
assume(stuff.length==that.stuff.length)
new User(stuff.zip(that.stuff).map(t => t._1.add(t._2)) toArray)
}
}
val u1 = new User(Array(new A(0)))
val u2 = new User(Array(new B(false)))
val u3 = u1.add(u1)
val u4 = u1.add(u2) // compile error: type mismatch
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.