2015-05-06 162 views
0

我想访问“静态”的成员,以实现以下目标:斯卡拉:有界泛型类型

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的值。

+0

Scala没有的“静态”在Java关键字 –

+0

我同意价值感的概念!我在标题中的引号中加上了“静态”,所以希望能让问题更清楚。 –

回答

1

typeSpecific不是静态成员,它属于SubASubB的实例,您没有这个实例。你也不能静态访问类型参数中的任何东西(它是一个类型,而不是一个对象)。

这不会按原样工作,因为您没有SubASubB的实例,您也不能通过new Tester[SubA]获取它们。但是,您可以要求TesterSuper的类型混合,以使其成为一个(因此具有typeSpecific)。这需要您将SuperSubASubB更改为特征,并且还会使您的实例成为匿名类。

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 

你把它的任何方式,你会需要的SubASubB一个实例。

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