警告中的關鍵詞是「推斷」。斯威夫特不喜歡推斷Void
,因爲它通常不是你的意思。但是,如果你明確地要求它(: Void
)那麼這很好,以及如果這是你的意思,你將如何平息警告。
重要的是要識別哪些類型是推斷的,哪些是顯式的。推斷是「從證據和推理中推斷或推斷(信息),而不是從明確的陳述中推斷出來」。它不是「猜測」或「選擇」的同義詞。如果類型不明確,那麼編譯器會產生一個錯誤。該類型必須是總是是明確的。問題是,是否明確定義,或通過推斷基於明確的信息定義。
此語句具有類型推斷:
let x = Foo()
類型的Foo()
明確已知,但x
的類型是基於整個表達式(Foo
)的類型推斷。它有明確的定義和完全明確的,但它是推斷。
這種說法沒有類型推斷:
let x: Foo = Foo()
而且,這裏還有沒有類型推論:
var x: Foo? = nil
x = Foo()
在第二行的類型x
(Foo?
)是明確的,因爲它在上面的行中被明確定義。
這就是爲什麼有些示例會生成警告(當存在Void
推斷時),而另一些則不會(僅當明確使用Void
時)。爲什麼我們關心推斷Void
?因爲它可能非常容易發生,並且幾乎沒有用處。例如:
func foo() {}
let x = foo()
這是合法的斯威夫特,但它生成一個「推斷爲有型‘()’」的警告。這是一個非常容易的錯誤。至少如果您嘗試分配不返回結果的結果,則至少需要警告。
那麼我們如何分配不返回結果的結果呢?這是因爲每個函數都返回一個結果。如果退貨是Void
,我們只允許忽略這些信息。請務必記住Void
並不意味着「無類型」或「無」。它只是()
的一個typealias,它是零元素的元組。它與Int
一樣有效。
上述代碼的完整形式是:
func foo() ->() { return() }
let x = foo()
這將返回相同的警告,因爲它是一回事。我們可以放棄->()
和return()
,但它們存在,因此如果我們願意,我們可以將()
指定爲x
。但是我們想要的是不可能的。我們幾乎肯定犯了一個錯誤,編譯器就此警告我們。如果由於某種原因我們想要這種行爲,那很好。這是合法的Swift。我們只需要更明確一些類型,而不是依賴於類型推斷,並警告將消失:
let x: Void = foo()
斯威夫特是在您的實例的產生警告非常一致,而且你真的希望這些警告。它根本不是任意的。
編輯:您加入不同示例:
var v = Optional<Void>()
這將生成錯誤:ambiguous use of 'init()'
。這是因爲編譯器不確定您的意思是Optional.init()
將是.None
還是Optional.init(_ some:())
,這將是.Some(())
。不明確的類型被禁止,所以你會得到一個硬性錯誤。
在Swift中,任何值都會隱式轉換爲等價的1元組。例如,1
和(1)
是不同的類型。第一個是Int
,第二個是包含Int
的元組。但Swift會默默地爲你轉換這些(這就是爲什麼你有時會在錯誤信息中令人驚訝的地方看到括號出現)。所以foo()
和foo(())
是一樣的東西。在幾乎所有可能的情況下,這並不重要。但在這種情況下,類型真的是()
,這很重要,並使事情變得模糊。
var i = Optional<Int>()
這明確地指Optional.init()
並返回nil
。
'v2'只聲明,試圖給它分配一個值,看看如果編譯器是確定與 – Cristik
@Cristic V2的右邊都有默認值爲零 – user3441734