Scala:访问 "static" 有界泛型类型的成员
Scala: access "static" member of bounded generic type
我想实现以下目标:
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 中可以实现这样的功能吗?这失败了,因为在 Tester.test
.
中找不到 T
的值
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
.
的实例
您将不得不结合使用反射和类型标签来获得您想要的结果。我警告你,它有点难看:
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 不是静态的,因为它是 class 的一部分,在 scala 中,静态成员仅在 objects/companion 对象中定义。使用对象做这样的事情会更干净:
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
我想实现以下目标:
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 中可以实现这样的功能吗?这失败了,因为在 Tester.test
.
T
的值
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
.
您将不得不结合使用反射和类型标签来获得您想要的结果。我警告你,它有点难看:
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 不是静态的,因为它是 class 的一部分,在 scala 中,静态成员仅在 objects/companion 对象中定义。使用对象做这样的事情会更干净:
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