我想实现以下目标:
abstract class Super {
def typeSpecific: Int
}
class SubA extends Super {
def typeSpecific = 1
}
class SubB extends Super {
def typeSpecific = 2
}
class Tester[T <: Super] {
def test = T.typeSpecific
}
val testerA = new Tester[SubA]
val testerB = new Tester[SubB]
testerA.test // should return 1
testerB.test // should return 2
在Scala中是否可以这样?此操作失败,因为在T
中找不到Tester.test
的值。
答案 0 :(得分:1)
typeSpecific
不是静态成员,它属于SubA
和SubB
的实例,您没有。您也无法静态访问类型参数中的任何内容(它是类型,而不是对象)。
这不会按原样运行,因为您没有SubA
和SubB
的实例,也无法通过new Tester[SubA]
获取它们。但是,您可以要求Tester
混合Super
类型以使其成为一个(因此具有typeSpecific
)。这需要您将Super
,SubA
和SubB
更改为特征,并且还会使您的实例成为匿名类。
trait Super {
def typeSpecific: Int
}
trait SubA extends Super {
def typeSpecific = 1
}
trait SubB extends Super {
def typeSpecific = 2
}
// The self-type `this: A =>` requires the mix-in.
class Tester[A <: Super] { this: A =>
def test = typeSpecific
}
val testerA = new Tester[SubA] with SubA
val testerB = new Tester[SubB] with SubB
scala> testerA.test
res2: Int = 1
scala> testerB.test
res3: Int = 2
您还可以要求A <: Super
作为Tester
的构造函数参数,这可能是更清晰的选项。
abstract class Super {
def typeSpecific: Int
}
class SubA extends Super {
def typeSpecific = 1
}
class SubB extends Super {
def typeSpecific = 2
}
class Tester[A <: Super](s: A) {
def test = s.typeSpecific
}
val testerA = new Tester(new SubA)
val testerB = new Tester(new SubB)
scala> testerA.test
res5: Int = 1
scala> testerB.test
res6: Int = 2
如果你削减它,你将需要一个SubA
或SubB
的实例。
答案 1 :(得分:0)
您必须使用反射结合typeTags来获得所需的结果。我警告你,这有点难看:
import scala.reflect.runtime.universe._
abstract class SuperClass {
def typeSpecific: Int
}
class SubA extends SuperClass {
def typeSpecific = 1
}
class SubB extends SuperClass {
def typeSpecific = 2
}
class Tester[T <: SuperClass: TypeTag] {
def test = typeTag[T].mirror.runtimeClass(typeOf[T]).newInstance.asInstanceOf[T].typeSpecific
}
我还觉得我应该提到typeSpecific不是静态的,因为它是类的一部分,在scala静态成员只在对象/伴随对象中定义。使用对象,做这样的事情会更干净:
trait SuperTrait {
def typeSpecific: Int
}
object SubA extends SuperTrait {
def typeSpecific = 1
}
object SubB extends SuperTrait {
def typeSpecific = 2
}
class Tester(testObject : SuperTrait) {
def test = testObject.typeSpecific
}
new Tester(SubA).test
new Tester(SubB).test