2012-08-07 62 views
11

我想使用抽象類型而不是類型參數。scala類的構造函數和抽象類型

在我的泛型類的構造函數,我想有泛型類型的參數,但代碼不編譯:

class SomeOtherClass(val s: S){ 
    type S 
} 

是「未發現:S型」 Scala編譯器錯誤

如果我使用一個類型參數,而不是一個抽象的類型,那麼它的工作原理:

class SomeClass[T](val t: T){ 
    //... 
} 

是否斯卡拉強迫我用一個類型參數,而不是一個抽象類,如果我想有一個構造函數中的泛型參數?

是否有另一種方法可以做到這一點?

回答

3

在這種情況下,您幾乎被迫使用泛型類型參數。你可以通過在類之外聲明類型來解決它,但是你需要實例化包裝器,然後對象,它會很快變得醜陋。

trait FooDef { 
    type T 
    class Foo(val x: T) 
} 
val ifd = new FooDef { type T = Int } 
val ifoo = new ifd.Foo(5) 
val sfd = new FooDef { type T = String } 
val sfoo = new sfd.Foo("hi") 
def intFoos(f: fd.Foo forSome { val fd: FooDef {type T = Int} }) = f.x + 1 
0

編譯器應該如何知道它應該使用哪種類型?要麼你必須直接指定類型,這沒有多大意義,或者使用泛型。有一種方法可以使它工作,但我認爲它不會對你有所幫助。

class SomeClass(s: SomeClass#S) { 
    type S 
} 

但是因爲SomeClass#S沒有定義,所以沒有它的實例。

+0

有趣的是,這將允許你創建新的SomeClass實例(5.asInstanceOf [SomeClass#S]){type S = Int}'。請注意,沒有安全性,演員陣容中的S仍未定義。 – Kaito 2012-08-07 12:43:56

+0

所以基本上做得對,我需要看另外兩個答案? – 2012-08-07 13:16:09

+0

@AntKutschera是的。 – Nicolas 2012-08-07 13:39:39

0

也許你想要這樣的事情?這樣,您可以有多個AbstractFooFactory的實例,每個產生Foo s,其中s的值不同。

trait AbstractFooFactory { 
    type S 
    def makeFoo(s:S):Foo 
    class Foo(val s:S) {} 
} 

object StringFooFactory extends AbstractFooFactory { 
    override type S = String 
    override def makeFoo(s:String) = new Foo(s) 
} 

val b = StringFooFactory.makeFoo("bar") 
val s:String = b.s 
1

當未指定抽象類型時,您的類需要是抽象的。所以你根本不需要參數。用抽象類型的等效是:

abstract class SomeOtherClass { 
    type S 
    val s: S 
} 

然後在使用現場:

val x = new SomeOtherClass { 
    type S = String 
    val s = "abc" 
} 

如果不帶參數,這裏的抽象類相當於一個特質。你最好使用特質,因爲它的限制較少(你只能擴展一個基類)。