2012-04-23 202 views
1

在一個抽象的泛型類使用領域我在斯卡拉是這樣的:初始化和斯卡拉

abstract class Point[Type](n: String){ 
    val name = n 
    var value: Type = _ 
} 

到目前爲止好。問題出現在擴展Point的類中。

case class Input[Type](n:String) extends Point(n){ 
    def setValue(va: Type) = value = va 
} 

setValue行我有這樣的問題:

[error] type mismatch; 
[error] found : va.type (with underlying type Type) 
[error] required: Nothing 
[error] def setValue(va: Type) = value = va 

我試圖與nullnull.asInstanceOf[Type]初始化,但結果是一樣的。

如何初始化值以便可以在setValue中使用?

回答

7

您應該指定一個Input工具Point與通用型Type,因爲就目前而言,不指定,它是作爲Nothing(我猜編譯器不能從setValue方法推斷出它)考慮。所以,你必須做到以下幾點:

case class Input[Type](n:String) extends Point[Type](n){ 
    def setValue(va: Type) = value = va 
} 

更多信息

我回答的編譯錯誤這個問題(它編譯於斯卡拉2.9.0.1)。此外,我將此案例類視爲現有類型的實現,如「Int」。在抽象類中_的使用當然是一個壞主意,但它並不是禁止的,但_並不總是空值,它是默認值,例如:var x:Int = _將賦值0x

+1

這個答案不正確。僅僅添加類型的情況下類,當他試圖用'setValue'與除'Nothing'任何其它類型不會編譯: '抽象類Point [T](n爲字符串){ VAR值:T = _ VAL名稱=正 } 情況下類輸入[T](n爲字符串)延伸點[T](N){ DEF的setValue(VA:T)=值= VA } 對象testTypedCaseClass { DEF測試(){ VAL富=輸入( 「foo」 的) foo.setValue( 「條」) 的println(富) } }' RESU lts在: 'type mismatch;' 編譯時 這是因爲他在'Point [T]'中聲明的值是'Nothing'。 – 2012-04-23 21:02:37

+0

不能相信我犯了這個簡單的錯誤。事實上,這是錯誤的一部分,但如果我改變了這一點,並保留其餘部分,它給了我同樣的錯誤。 – 2012-04-23 21:10:59

+0

作爲@JackViers提到的,使用默認值,再加上一些通用的類型爲價值是相當混亂,這將實現默認值加上一個setter這是不是在同一層上,但我不把所有的代碼,所以我建議一個簡單的「補丁」。請毫不猶豫地在您的問題中提供更多細節。 – 2012-04-23 21:14:00

1

嘗試以下操作:

包inputabstraction

abstract class Point[T](n:String){ 
    def value: T 
    val name = n 
} 

case class Input[T](n:String, value:T) extends Point[T](n) 

object testTypedCaseClass{ 
    def test(){ 
    val foo = Input("foo", "bar") 
    println(foo) 
    } 
} 

一個簡單的應用,以檢查它的工作原理:

import inputabstraction._ 


object TestApp extends Application{ 
    testTypedCaseClass.test() 
} 

說明

您所做的第一個錯誤是case class Input[Type](n:String) extends Point(n){。 Point是一個類型化的類,因此當您使用extends Point(n)調用超類的構造函數時,您需要指定Point的類型。這是這樣完成的:extends Point[T](n),其中T是您計劃使用的類型。

第二個錯誤是您既定義和聲明值:T在這裏:var value: Type = _。在這個聲明中,_是一個值。它的值是Nothing。 scala編譯器從此推斷出Point[T]Point[Nothing]。因此,當您嘗試將其設置爲setValue方法正文中的類型時,必須將其設置爲Nothing,這可能不是您想要的。如果您嘗試將其設置爲除Nothing之外的任何內容,則會從上面得到類型不匹配,因爲由於您使用了_,所以鍵入的值爲Nothing

第三個錯誤是使用var而不是valdefvaldef可以互換覆蓋,這意味着亞型可與valdef覆蓋,和Scala編譯器會看着辦吧你。它是用來定義瓦爾斯如使用抽象類和特質def功能的最佳做法,因爲亞型構造函數初始化順序是一件很困難的事情得到正確的(沒有爲編譯器如何確定如何從它的超類型構造一個類的algorithm )。 TL#DR ===在超類型中使用def。大小寫類參數會自動生成val字段,由於您要擴展Point,因此將創建val值字段,該字段將覆蓋Point[T]中的def值字段。

你可以擺脫這一切Type ||因爲類型推斷和Point是抽象的事實,因此可以通過val擴展值。

做的依賴注入這樣的首選方式是cake pattern,但這個例子我已經提供了您的用例的作品。

+0

感謝您的解釋。但是,如果我將value定義爲'def value:Type',它會給我錯誤:'value value_ =不是test.package.Input [Type]的成員' – 2012-04-23 21:10:17

+0

T = Type。我相信類型抽象必須全部大寫。當它們混合使用時,表示您正在使用特定類型:[S]正常。 [字符串]不是。 – 2012-04-23 21:26:49

+0

嗯......我不認爲Scala是區分大小寫的。 – 2012-04-23 21:28:24