2016-10-01 198 views
2

下面的类型TFruit的子类型。 Apple也是Fruit的子类型。那么,为什么在下面使用类型归属时,编译器不会将Apple强制转换为T.为什么我们需要一个明确的演员才能使其工作?推断类型时,强制规则是什么?子类型和类型强制

trait Fruit 
case class Apple(id: String) extends Fruit 

type T <: Fruit 

val t: T = Apple("apple") // why doesn't the compiler coerce Apple to T? 

val t: T = Apple("apple").asInstanceOf[T] // works! 

回答

1

让我们简化这一点。用梨子和水果和胎儿一起吃T。

trait Fetus 
class Apple extends Fetus 
type Pear <: Fetus 

val t: Pear = new Apple() 

我们宣布胎儿,然后我们说“苹果是胎儿”,然后“梨是胎儿”。 我们的逻辑到目前为止是正确的。但是,我们试图“把苹果放入梨盒”。这是我们的错误。

让我们来看另一个例子:

trait Fetus 
class Apple extends Fetus 
type Fruit >: Apple <: Fetus 

val t: Fruit = new Apple() 

在这里,我们宣布的胎儿,那么我们说:“苹果是胎儿”,然后我们说,“水果东西在苹果和胎儿之间的中间”。换句话说,我们建立了以下等级:胎儿 - >水果 - >苹果。所以,现在苹果是水果的子类型,你可以“把苹果放入水果箱”。

UPDATE:

一个Pear绝对不能和Apple,像猫不能是狗,尽管他们都是动物。你可以通过层次结构只能垂直,但不能水平:

Creature 
    | 
Animal 
    _|_ 
/ \ 
Dog Cat 
     \ 
     White Cat 
+0

所以,“Pear <:胎儿”意味着Pear是'胎儿的**特定**亚型和**特定**亚型不是'Apple'?但是,为什么'梨'不能成为'苹果'?所有编译器都知道'Pear'是'Fetus'的子类型。它可以或不可以是Apple。 – Samar

+0

我更新了答案 –

+0

感谢您的回答,现在有道理。 – Samar

1

我想你混淆了定义 type T <: Fruit的意义:这是一个抽象类型确定指标(不同于type T = Fruit这是一个类型别名)。抽象类型不要创建类T延伸Fruit,而是抽象声明必须在要使用的某个子类中重写。

Learning Scala, chapter 10

...抽象类型是可以解决零,一个或多个类规格。他们以同样的方式输入别名工作,但作为规范他们是抽象的,不能用来创建实例

声明,该声明type T <: Fruit只能属于一类/特征(不是对象,也不顶级别的定义),因为它没有意义,直到这个类/特质被扩展。在定义的地方,它仍然是抽象的,因此编译器无法确定Apple是否对其进行了扩展。

使用这样的定义的一个例子:

trait Price { 
    type T <: Fruit 
    def printPrice(x: T): Unit 
} 

class ApplePrice extends Price { 
    override type T = Apple 
    override def printPrice(x: Apple): Unit = ??? 
} 

这里,ApplePrice必须重写这个抽象类的东西。的Price另一亚类可能与一些不同的(例如Banana extends Fruit),其应明确的是放置在Price表达val t: T = Apple("apple")不能编译覆盖此 - 对一些可能的延伸类,T不是Apple,也不Apple延伸T

+0

感谢您指出'抽象类型'与'类型别名'的东西。但是,抽象类型看起来可以用作类型归属(类似于说抽象类型确实意味着一个类)?另外,您怎么看待德米特里的推理?这看起来很直观。 – Samar

+1

德米特里的答案是完全正确的,我只是假设抽象定义的本质是需要澄清的问题。最终,这两个答案一起给出了完整的画面:作为抽象,类型T_might_最终成为某种类型,它不是Apple的超类型,所以编译器不能让“Apple”分配给它。 –

+0

啊,编译器只能强制'Apple'键入'T' iff'T'是超类型'Apple'。而这并不成立,因为'T'可能是Apple的子类型,或者实际上并非如Dimitry所提到的水平放置。谢谢,现在一切都合情合理! – Samar