這不起作用的原因是因爲A: B
語法需要一個通用的佔位符表示任何符合協議或從基類繼承的類型。由於String
是一個結構,而不是一個協議或類,所以會出現一個錯誤(「從非協議類繼承,非類類型'String'」)。如果您嘗試枚舉類似Optional
的枚舉,則會得到相同的結果
這是爲什麼呢?泛型的目的是讓你編寫多於一種可能類型的代碼,然後在編譯時讓Swift允許將這個函數應用於多種不同的類型以滿足這個要求。因此,當你說func f<S: String>(c: S)
時,你會定義一個通用佔位符S
,它只能代表一種String
而沒有其他類型,這是毫無意義的 - 你可以l指定String
作爲非泛型參數,即func f(s: String)
,因爲它沒有可能的其他類型。在另一方面
類確實允許繼承,所以如果你有一個類MyClass
,你可以因爲在編譯時寫func f:<S: MyClass>(c: S)
,也許你可以通過在MyInheritedClass
,從MyClass
繼承的類。
雖然結構可以符合協議。因此,例如,假設你想寫的東西,交換隻有一個人比另一個更大的值:
func swapIfGreater<T: Comparable>(inout a: T, inout b: T) {
// this is allowed because conformance to the the
// Comparable protocol guarantees > is available
if a > b {
// avoid temporaries with this one weird trick :)
(a, b) = (b, a)
}
}
// i and j are Ints (a kind of struct)
var i = 40, j = 30
swapIfGreater(&i, &j)
// s1 and s2 are Strings
var s1 = "zebra", s2 = "aardvark"
swapIfGreater(&s1, &s2)
// Bool doesn’t support the Comparable protocol
// (false is not 「less than」 or 「greater than」 true)
// so this won’t compile:
var b1 = true, b2 = false
swapIfGreater(&b1, &b2)
在編譯時,當swapIfGreater
被調用時,斯威夫特看上去在插槽中使用的類型通用佔位符T
(這裏是Int
或String
),並檢查它們是否符合要求(它們需要符合協議Comparable
)。如果是這樣,你可以認爲它是專門爲你傳入的每種有效類型寫入一個函數版本:
// It’s as if Swift writes two versions of swapIfGreater for you automatically:
func swapIfGreater(inout a: Int, inout b: Int) {
if a > b {
(a, b) = (b, a)
}
}
func swapIfGreater(inout a: String, inout b: String) {
if a > b {
(a, b) = (b, a)
}
}
爲什麼struct不能被擴展?教程說「擴展爲現有類,結構或枚舉類型添加新功能」。 – 2014-12-19 07:03:26
對不起,這是一個不好用的單詞。可以使用「擴展」來擴展結構。但是他們不能通過繼承來「擴展」。 不同之處在於對「擴展」有特殊限制(例如,它們不能存儲新的成員變量,這會增加類型的大小) – Zenton 2014-12-19 07:05:41