2013-10-04 36 views
0

按照scala docs不一致的行爲與空型Scala中

空值是所有引用類型的一個子類型;

所以理論上,在這個例子中,我們可以假設NullFoo(引用類型)的子類型,我們應該能夠嘗試調用bar方法上Null類型的實例。實際上,我們不能在編譯時錯誤代碼片段,錯誤號爲value bar is not a member of Null


case class Foo(bar: String) 

val n: Null = null 
n.bar 

Try it


我認爲這讓我們抓住這個在編譯時有道理的,因爲作爲斯卡拉文檔也say[Null's] only instance is the null reference,但我認爲更準確的錯誤消息將是Calling bar on type Null can only result in a NullPointerException

我的問題是關於下面的代碼段,這並不在編譯時失敗,而是在運行時失敗了NullPointerException


val n: Null = null 
n.toString 

Try it


我假設這是因爲Null類型並不是真正的子類化其他所有引用類型,只有子類AnyRef,但是有什麼理由說明這個sh不會拋出編譯時錯誤(或至少警告),該代碼只能導致NullPointerException?是否故意撥打null.barnull.toString表現不同?

回答

0

Null is a subtype of all reference types; - 這意味着類似的東西:

val n: Foo = null 
n.bar //throws NPE 

val a: String = null 
a.charAt(0) //NPE again 

因此可以這樣說Null是所有引用類型的子類型。

編輯:

val n: Null = null 
n.bar 

部分不正確。據斯卡拉文檔:

abstract final class Null extends AnyRef 

AnyRef犯規」有一個bar。你不能這樣說,對吧?

val n: AnyRef = "" 
n.charAt(0) //won't compile 
+0

但肯定這兩個說法有衝突嗎?在[this]中(http://www.cmi.ac.in/~madhavan/courses/pl2009/lecturenotes/lecture-notes/node28.html)子類型的定義如果每個函數都可以使用,則類型B是A的子類型在A類型的對象上調用也可以在類型爲B的對象上調用。如果我的例子中,如果不能在類型爲'Null'時調用'.bar',那麼輸入'Null'不是'Bar'子類型。 – theon

+0

嗯,我不確定,但它似乎像這個表達式('val n:Foo = null')翻譯成類似於「讓Null'成爲'Foo'的子類型」,所以'val n:空=空轉換爲一個簡單的'空'。考慮兩個類 - 'Foo(bar:String)'和'Bar(foo:String)'。在這種情況下,如果你寫'val n:Null = null'它應該是哪個子類型? – serejja

+0

它應該是'Foo'和'Bar'的子類型,但這是一個好點;多個類繼承在scala中是不可能的,所以它不可能。我一直在查看子類型和繼承,但也許他們需要在Scala中被認爲是不同的東西。 – theon