2016-08-22 103 views
5

我知道斯卡拉沒有什麼是底部類型。當我看到API是從層次結構頂部的「任何」擴展而來的。斯卡拉沒有數據類型

既然Scala不支持多繼承,那麼我們怎麼能說它是底層類型。換句話說,它並不直接繼承Seq,List,String,Int等所有的類或特性。如果是這種情況,我們怎麼能說它是所有類型的底部?

我的意思是,如果我們能夠將List [Nothing](Nil)分配給List [String],因爲List在scala中是協變的,因爲Nothing和String類型之間沒有直接關聯,所以它是可能的。正如我們所知,沒有什麼是最基本的類型,但我很難看到String和Nothing之間的關係,正如我在上面的例子中所述。

感謝&問候,穆罕默德

+1

'對於所有類型'T'都沒有擴展T'。因此,'Nothing extends String' –

+2

我不是100%確定你的問題是什麼,但是編譯器知道Nothing並且知道它是其他類型的子類型,因爲它在編譯器中是硬編碼的。標準庫中沒有真正的Nothing.scala文件,它說'特性Nothing用Int來擴展字符串,用Double ...來擴展。 –

回答

3

現在既然斯卡拉不支持多重繼承

斯卡拉不支持多重繼承,使用特質混入。這是目前不可交換的,即類型A with BB with A不一致(這將在Dotty中發生),但仍然是多重繼承的形式,實際上也是Scala的一個強項,因爲它通過線性化規則解決了鑽石問題。

順便說一句,Null是另一種底層類型,它繼承自Java(因爲可以在任何可能的地方拋出一個運行時異常,所以它也可以說有一個底層類型Nothing)。

我認爲你需要區分類繼承和類型邊界。將Nothing定義爲底部類型並不矛盾,但它並不「明確」從您想要的任何類型繼承,例如List。它更像是一種能力,能夠拋出異常。

如果我們能夠分配列表[沒什麼](無)列出[字符串]如列表是Scala它是如何可能協變的,因爲沒有什麼與字符串類型之間沒有直接的關聯

是的,底部類型的想法是,Nothing也是(其中包括許多其他事項)String的子類型。所以,你可以寫

def foo: String = throw new Exception("No") 

這隻能是因爲Nothing(拋出異常的類型)大於聲明的返回類型String更具體。

2

tl; dr摘要Nothing是每種類型的子類型,因爲規範是這樣說的。它不能從語言中解釋。每種語言(或至少幾乎每種語言)都有一些無法從語言中解釋的核心內容,例如,即使我們不寫一個extends子句,該類也會隱含地獲得一個超類,但即使每個類都有一個超類,也沒有超類。或者Ruby中的「自舉悖論」,ObjectClass的一個實例,但ClassObject的子類,因此Object是其本身的間接實例(甚至更直接地:ClassClass的實例)。


我知道斯卡拉沒有什麼是底部類型。當我看到API是從層次結構頂部的「任何」擴展而來的。

既然Scala不支持多繼承,那麼我們怎麼能說它是底層類型。

有兩種可能的答案。

簡單和簡短的答案是:because the spec says so。規格說Nothing是所有類型的子類型,所以Nothing所有類型的子類型。怎麼樣?我們不在乎。規範說明是這樣,所以就是這樣。讓編譯器設計人員擔心如何在編譯器中表示這個事實。你關心Any能夠超類嗎?你關心def在編譯器內部是如何表示的嗎?

稍長的答案是:是的,這是真的,從AnyAny只有Nothing繼承。但!繼承與子類型不同。在斯卡拉,繼承和子類型緊密結合在一起,但它們並不是一回事。 Nothing只能從一個類繼承的事實並不意味着它不能是多於一種類型的子類型。類型與類不是一回事。

事實上,具體而言,規範甚至沒有說Nothing是所有類型的子類型。它只說Nothingconforms to all types

換句話說,它並不直接繼承Seq,List,String,Int等所有的類或特性。如果是這種情況,我們怎麼能說它是所有類型的底部?

再一次,我們可以說,因爲規範說我們可以這麼說。

我們怎麼能說def定義了一個方法?因爲the spec says so。我們怎麼能說a b c意味着與a.b(c)a b_: c意味着相同的事情{ val __some_unforgeable_id__ = a; c.b_:(__some_unforgeable_id__) }?因爲the spec says so。我們怎麼能說""是一個字符串,而''是一個字符?因爲the spec says so

我的意思是,如果我們能夠將List [Nothing](Nil)分配給List [String],因爲List在scala中是協變的,因爲Nothing和String類型之間沒有直接關聯。

是的,有類型NothingString之間有直接的關係。NothingString的亞型,因爲Nothing的所有類型的亞型,包括String

正如我們所知,沒有什麼是最基本的類型,但我很難看到String和Nothing之間的關係,正如我在上面的例子中所述。

StringNothing之間的關係是NothingString子類型。爲什麼?因爲規範是這樣說的。

編譯器知道NothingString亞型它知道1以同樣的方式是Int一個實例,並且具有+方法,即使如果你看一下Scala的標準庫的源代碼,the Int class is actually abstract and all its methods have no implementation

Someone, somewhere wrote some code within the compiler that knows how to handle adding two numbers,儘管這些數字實際上表示爲JVM基元,並且甚至不存在於Scala對象系統中。同樣,someone, somewhere wrote some code within the compiler that knows that Nothing is a subtype of all types即使這個事實在the source code of Nothing中沒有被表示(甚至不能表示)。

+0

我在一段時間內看到的最規範的密集答案之一:) –

+0

我試圖重新迭代一種「無所謂」的態度,幾乎令人討厭地經常反覆指向規範,因爲我覺得這個「不關心」的態度在於編程的核心:抽象和重用。如果規範說它有效,那麼我不在乎它是如何工作的,我只是使用它。 (實際上,這根本不是真的,我是一個好奇的人,我對編譯器和虛擬機以及其他東西非常感興趣,但是我認爲這是一種有用的態度,可以使用,甚至更重要的是設計抽象。) –

+0

我部分同意以那種態度。正如你自己所說的那樣,有一些熱切的開發人員真正關心編譯器如何使Nothing成爲所有類型的子類型。我認爲,好的回答應該引導人們發現真正發生的地方,好奇心。但我確實同意,關於SO的大部分初學者問題都不是這樣的。 –