[英]Scala: access “static” member of bounded generic type
I want to achieve the following: 我要实现以下目标:
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
Is something like this possible in Scala? 这样在Scala中可能吗? This fails because the value of T
is not found in Tester.test
. 这将失败,因为在Tester.test
找不到T
的值。
typeSpecific
is not a static member, it belongs to instances of SubA
and SubB
, which you don't have. typeSpecific
不是静态成员,它属于SubA
和SubB
实例,而您没有这些实例。 You also can't statically access anything from a type parameter (it's a type, not an object). 您也不能从类型参数(它是类型,而不是对象)中静态访问任何内容。
This won't work as is, because you don't have instances of SubA
and SubB
, nor can you obtain them via new Tester[SubA]
. 这将无法正常工作,因为您没有SubA
和SubB
实例,也无法通过new Tester[SubA]
获得它们。 But you can require that Tester
mixes in a type of Super
in order to make it one (and thus have typeSpecific
). 但是您可以要求Tester
混合使用Super
类型,以使其成为Super
类型(并因此具有typeSpecific
)。 This would require you change Super
, SubA
, and SubB
to traits, and would also make your instance anonymous classes. 这将需要您将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
You could also require A <: Super
as a constructor parameter for Tester
, which is probably the cleaner option. 您还可能需要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
Any way you cut it, you're going to need an instance of SubA
or SubB
. 以任何方式削减它,都将需要SubA
或SubB
的实例。
You're going to have to use reflection combined with typeTags to get your desired result. 您将必须结合使用反射和typeTags来获得所需的结果。 I warn you, it's somewhat ugly: 我警告你,这有点丑陋:
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
}
I also feel I should mention that typeSpecific is not static as it is part of a class, in scala static members are defined in objects/companion objects only. 我还觉得应该提到typeSpecific不是静态的,因为它是类的一部分,在scala中,静态成员仅在对象/伴侣对象中定义。 Using objects it would be cleaner to do something like this: 使用对象可以更干净地执行以下操作:
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
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.