2016-06-10 59 views
0

Scala n00b here。很確定我理解PDT,但是確定並且遇到問題;這裏有一個先前的問題Scala types: Class A is not equal to the T where T is: type T = A與示例代碼我將在這裏重現:路徑依賴類型示例不起作用

1: class Food 
2: class Fish extends Food 
3: class Grass extends Food 
4: 
5: abstract class Animal { 
    6: type SuitableFood <: Food 
    7: def eat(food: SuitableFood) 
8: } 
9: 
10: class Cow extends Animal { 
    11: type SuitableFood = Grass 
    12: override def eat(food: Grass) {} 
13: } 
14: 
15: val bessy: Animal = new Cow // [1] 
16: 
17: bessy eat (new bessy.SuitableFood) // [2] 

樓主說,這編譯,我認爲它應該,但它不會。如果我把它粘貼到斯卡拉REPL它成功地創建BESSY [1]:

scala> val bessy: Animal = new Cow 
bessy: Animal = [email protected] 

但[2],給了我,我不明白的錯誤:

scala> bessy.eat(bessy.SuitableFood) 
<console>:17: error: value SuitableFood is not a member of Animal 
     bessy.eat(bessy.SuitableFood) 
        ^

如果我貼吧成一個文件和'scalac'它,我也一樣。爲什麼? bessy是一個牛的對象,其中type SuitableFood = Grass定義在其中,bessy.SuitableFood是一個類的類型(不是嗎?)。 有什麼問題?

回答

2
  1. 您在(new bessy.SuitableFood)中缺少new

  2. 你解決這個問題之後,bessy被定義爲具有Animal類型,而不是Cow,所以編譯器知道bessy.SuitableFoodGrass:它只是一個抽象類,所以new bessy.SuitableFood不工作(如new A沒有按當A是類型參數時)。例如。考慮Animal的某些其他子類型可能會聲明type SuitableFood = Food,而new Food是非法的。 我已經檢查過了,它在2.10.6中編譯,但我相信這是一個已修復的錯誤。

因此,我認爲「新bessy.SuitableFood」將返回一個合適的食物,因爲.SuitableFood是一種虛擬式的,所以,當是「牛」,那麼「SuitableFood」是「草」。如果他們不這樣做,我不會看到PDT的價值。

這裏的PDT的一點是,如果你做一個bessy.SuitableFoodbessy可以吃;她不能吃spot.SuitableFood(除非編譯器可以靜態地知道它是一個子類型)。但是這個例子沒有給出產生bessy.SuitableFood的方法,因爲沒有理由假設(也沒有辦法告訴編譯器)type SuitableFood是一個帶有公共無參數構造函數的類。您可以通過添加一個方法來Animal修復:

abstract class Animal { 
    type SuitableFood <: Food 
    def eat(food: SuitableFood) 
    def newSuitableFood(): SuitableFood 
} 

class Cow extends Animal { 
    ... 
    def newSuitableFood() = new Grass 
} 

現在bessy.eat(bessy.newSuitableFood)將編譯和工作。

+0

我沒有得到第一點,那裏有一個'新',就在你的代碼副本中。你能指出哪條線有缺陷嗎?我已將行號添加到原始文件中以提供幫助。重新考慮你的第二點,「解決這個問題後,bessy被定義爲具有類型Animal,而不是Cow,所以編譯器不知道bessy.SuitableFood是Grass」確實!因此,我認爲「新的bessy.SuitableFood」將返回一個合適的食物,因爲 .SuitableFood會是一種虛擬類型,所以當是'牛'時,那麼'SuitableFood'將是'草'。如果他們不這樣做,我不會看到PDT的價值。 – user3779002

+0

「[2],給了我一個我不明白的錯誤:'scala> bessy.eat(bessy.SuitableFood)'」。這裏沒有'新'。 –

+0

「因此,我認爲」新bessy.SuitableFood「會返回一個合適的食物,因爲 .SuitableFood會是一種虛擬類型」但是,爲什麼你會期望這種類型有一個沒有參數的構造函數?我編輯了答案來解釋如何正確執行此操作。 –