2014-09-03 77 views
1

我有一些簡單的特徵(在下面的例子中的實體),由我的應用程序中的大小寫類擴展。我想創建一個EntityMapper特徵,它提供了一個接口來處理擴展實體特徵的案例類(下面的例子中的Foo)。我認爲我應該能夠使用泛型和邊界相當容易地做到這一點,但我已經花了幾個小時,並且我沒有得到它的正確工作。下面的代碼是我認爲我應該能夠做到的,但是由於編譯器錯誤而失敗。該錯誤是在Scala中使用泛型實現特徵的正確方法是什麼?

Test.scala:15:錯誤:值id不是

package experiment 

trait Entity { 
    val id: Option[Long] 
} 

case class Foo(val id: Option[Long] = None) extends Entity 

trait EntityMapper { 
    def create[E <: Entity](e: E): E 
} 

object FooMapper extends EntityMapper { 
    def create[Foo](e: Foo): Foo = { 
     println(e.id) 
     e 
    } 
} 

object Main extends App { 
    val foo = FooMapper.create(Foo(None)) 
} 

我已經嘗試了幾種不同的東西來解決類型參數的Foo \ 的println(e.id)的成員問題,但沒有任何工作。如果我註釋掉問題行「println(e.id)」,它會進行編譯,但這並不有用,因爲我無法訪問或修改Foo的任何屬性。

我已經嘗試對映射器特徵使用協變參數,然後將該類型提供給FooMapper對象定義,但是會產生相同的錯誤。該嘗試的代碼如下:

trait EntityMapper[+Entity] { 
    def create[E <: Entity](e: E): E 
} 

object FooMapper extends EntityMapper[Foo] { 
... 
} 

我也試圖實現與簡單的繼承同樣的事情,但我不能正確地限制FooMapper類型參數,只需要FOOS,我必須作出方法簽名匹配這正是我開始試圖用泛型綁定類型來實現它的原因。該嘗試的代碼如下:

trait EntityMapper { 
    def create(e: Entity): Entity 
} 

object FooMapper extends EntityMapper { 
    def create(e: Foo): Foo = { 
     println(e.id) 
     e 
    } 
} 

返回的錯誤碼是:

Test.scala:13:錯誤:對象創建不可能的,因爲在方法類型的性狀EntityMapper(例如創建:實驗。 Entity)experiment.Entity is not defined

(請注意,experiment.Entity與experiment.Foo不匹配:package實驗中的Foo類是包實驗中trait實體的子類,但方法參數類型必須完全匹配。)

object FooMapper extends EntityMapper { 
    ^

任何幫助將不勝感激。我正在使用Scala版本2.10.3。

回答

3

您可以在幾個方面

  1. 指定的特質泛型類型約束脩正這個錯誤。

    性狀EntityMapper [E <:實體] { DEF創建(E:E):電子 }

    對象FooMapper延伸EntityMapper [美孚] { DEF創建(例如:富):富= { 的println(E。ID) Ë } }

  2. 使用參數化的類型

    性狀EntityMapper { 類型E <:

    對象FooMapper延伸EntityMapper {Ê }:實體 DEF創建(E:E) type E = Foo def create(e:Foo):Foo = { println(e.id) e } }

查看Scala: Abstract types vs generics,以獲得有關這兩種方法的更多背景信息。

相關問題