2016-06-10 58 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会是一种虚拟类型”但是,为什么你会期望这种类型有一个没有参数的构造函数?我编辑了答案来解释如何正确执行此操作。 –