2015-05-06 159 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