2016-10-01 219 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