2016-12-13 98 views
1

我覺得我應該以這樣一個事實開頭,即我正在用sbt構建我的項目。斯卡拉,爲什麼我不需要導入推導類型

我的問題是,如果在編譯時某個方法返回某個未導入類型的東西,則在我調用該方法的文件中,只要我使用類型推斷,就會編譯所有內容。一旦我嘗試將我的函數的返回值創建的var/val分配給unimported類型,我得到一個編譯器錯誤。

可以說我有兩個包中的兩個類。包中的類爲App,包main和類Importedlibraries。讓我們進一步說,我們在包main中有一個類ImportedFactory,並且這個類有一個創建類型爲Imported的對象的方法。

此代碼編譯就好:

class App() { 
    // method return object of type Imported 
    val imp = ImportedFactory.createImportedObject() 
} 

這不:

class App() { 
    // method return object of type Imported 
    val imp : Imported = ImportedFactory.createImportedObject() 
} 

這又一次做:

import libraries.Imported 

class App() { 
    // method return object of type Imported 
    val imp : Imported = ImportedFactory.createImportedObject() 
} 

這似乎是很奇怪的行爲。這對編譯時類型推斷的語言來說是正常的,而且由於我的無知,直到現在我還沒有注意到它在go/C++中?

兩種有效方法之一(導入&顯式類型與傳染)有優點/缺點比其他? (當然,期望的是一個更明確和詳細,另一個更短)

這是黑魔法還是斯卡拉編譯器以相當直接的方式完成這些扣除?

回答

1

注:您會得到更好的搜索結果與術語類型推斷

隨着val imp = ImportedFactory.createImportedObject()你讓編譯器弄清楚什麼類型的imp應根據類型推斷。無論什麼類型的createImportObject返回,這就是imp類型。

使用val imp : Imported = ImportedFactory.createImportedObject()您明確指出impImported。但編譯器不知道你的意思,除非你......導入......它。

兩種方法各有優點:

推斷類型

推斷類型,當你扔在一起的代碼,其中類型應該是顯而易見的是巨大的:

val i = 1 // obviously `i` is an int 
val j = i + 10 // obviously still an int 

這也是很大的對於當地的瓦爾/瓦爾型這種類型會太痛苦寫

val myFoo: FancyAbstractThing[TypeParam, AnotherTypeParam[OhNoMoreTypeParams]] = ... 
// vs 
val myFoo = FancyThingFactory.makeANewOne() 

缺點是,如果您已允許公共def/val具有推斷類型,則確定如何使用該方法可能會更困難。由於這個原因,省略類型註釋通常只用於簡單的常量,並且在「客戶代碼」不必看的本地vals/vars中。

明確的類型

當你想要寫庫上下的代碼(即公共丘壑/ DEFS),慣例是顯式輸入。

可能就是這個最簡單的原因是因爲這樣的:

def myLibraryMethod = { 
    // super complicated implementation 
} 

是很難理解比

def myLibraryMethod: String = { 
    // super complicated implementation 
} 

另一個好處明確,輸入你的代碼是當你想揭露less-具體類型比實際值多:

val invalidNumbers: Set[Int] = TreeSet(4, 8, 15, 16, 23, 42) 

在這個例子中,你不要w螞蟻客戶端代碼需要注意,您的invalidNumbers實際上是一個TreeSet。這是一個實現細節。在這種情況下,你隱藏了一些信息,雖然是真的,但會分散注意力。

5

導入的唯一事情就是在當前範圍內提供一個不完全限定的名稱。你也可以同樣這樣寫:

的原因,你import libraries.Imported是爲了使較短的名稱Imported可爲你寫。如果你讓編譯器推斷出這個類型,你就不會在代碼中提到這個類型,所以你不必導入它的較短的名字。

順便說一下:這與C++中的動態轉換無關。在你的代碼中工作的唯一機制是類型推斷。

+0

我挪用了動態鑄造這個術語,這可能確實對我的問題造成了很多混淆(並且缺乏建議),對不起。 – George