2011-05-12 89 views
3
trait A { 
    trait B { 
    def foo: A.this.B = new B{} 
    def bar: A#B  = foo 
    def baz: A.this.B = bar // type mismatch; found : A#B required: A.this.B 
    } 
} 

我對嗎A.this.B是一個路徑依賴型?! (這是我迄今爲止的理解) 以上示例是否表示A.this.B類型是A#B的子類型? (如果是的話,我猜想區別在於A.this.B的一個實例引用了A的實例,而A#B不是這樣的實例嗎?) 有沒有人知道一個能夠解決這兩種類型混淆的啓發式解釋?是一個路徑依賴類型的一個子類型?

+0

與使用「A#B」的語法解釋什麼聯繫呢?第一次看到這個,謝謝 – 2011-05-12 11:45:17

+2

'A#B'被稱爲*類型投影*。 – 2011-05-12 12:42:14

回答

14

Scala中優秀的書編程有着相當不錯的explanation

class Outer { 
    class Inner 
} 

在斯卡拉,內部類使用表達式Outer#Inner而不是Java的Outer.Inner來解決。 .語法是爲對象保留的。例如,假設您實例Outer類型的兩個對象,像這樣:

val o1 = new Outer 
val o2 = new Outer 

這裏o1.Innero2.Inner兩種路徑依賴的類型(和他們是不同類型的)。這兩種類型都符合(是更一般類型Outer#Inner的(是其中的子類型)),它表示具有Outer類型的任意外部對象的Inner類。相比之下,o1.Inner類型引用具有特定外部對象的內部類(從o1引用的那個)。同樣,o2.Inner類型引用具有不同的特定外部對象(從o2引用的一個)的Inner類。

在Scala中,和Java一樣,內部類實例持有對封閉外部類實例的引用。例如,這允許內部類訪問其外部類的成員。因此,如果不以某種方式指定外部類實例,則不能實例化內部類。一種方法是在外部類的主體內部實例化內部類。在這種情況下,將使用當前的外部類實例(由此引用)。另一種方法是使用路徑依賴類型。例如,由於類型,o1.Inner,名稱的特定外對象,可以實例化:

scala> new o1.Inner 
res1: o1.Inner = [email protected] 

將所得內對象將包含一個參考到其外對象,從o1引用的對象。相比之下,由於類型Outer#Inner不名的Outer任何特定的情況下,你不能創建它的實例:

scala> new Outer#Inner 
<console>:6: error: Outer is not a legal prefix for 
    a constructor 
     new Outer#Inner 
       ^
5

簡而言之:是的,它是

如果你願意,你可以考慮A#B有一個抽象的參考含A(因此不能直接施工的,作爲任何抽象類型),該參考被用混凝土製成在路徑依賴的子類中。

+1

謝謝,由於抽象成員作爲對「A」實例的引用而將'A#B'想象爲抽象類型,這讓我認爲它更好。 – 2011-05-12 11:50:04

+0

的確很好解釋。 – 2011-05-12 21:48:26

+0

@丹尼爾 - 我知道你只是說,因爲你會用完全相同的方式解釋它:) – 2011-05-12 22:54:12

2

是的,這是一個路徑依賴類型。是的,B的所有實例都是A#B的成員。需要注意的是,你不能直接構造A#B的情況下,B的所有實例必須有外部的引用,例如