3 回答

TA貢獻(xiàn)1851條經(jīng)驗(yàn) 獲得超3個(gè)贊
A Thing<Vanilla>不是Thing<Flavor>。Thing不是協(xié)變的。Swift中無(wú)法表達(dá)Thing協(xié)變。這有充分的理由。如果沒(méi)有嚴(yán)格的規(guī)則就允許您要求的內(nèi)容,則可以編寫(xiě)以下代碼:
func addElement(array: inout [Any], object: Any) {
array.append(object)
}
var intArray: [Int] = [1]
addElement(array: &intArray, object: "Stuff")
Int是的子類(lèi)型Any,因此如果[Int]是的子類(lèi)型[Any],則可以使用此函數(shù)將字符串追加到int數(shù)組。這破壞了類(lèi)型系統(tǒng)。不要那樣做
根據(jù)您的實(shí)際情況,有兩種解決方案。如果是值類(lèi)型,則將其重新打包:
let thing = Thing<Vanilla>(value: Vanilla())
dict["foo"] = Thing(value: thing.value)
如果是參考類(lèi)型,請(qǐng)?jiān)谄渑赃吋由项?lèi)型橡皮擦。例如:
// struct unless you have to make this a class to fit into the system,
// but then it may be a bit more complicated
struct AnyThing {
let _value: () -> Flavor
var value: Flavor { return _value() }
init<T: Flavor>(thing: Thing<T>) {
_value = { return thing.value }
}
}
var dict = [String:AnyThing]()
dict["foo"] = AnyThing(thing: Thing<Vanilla>(value: Vanilla()))
類(lèi)型擦除器的具體信息可能會(huì)有所不同,具體取決于您的基礎(chǔ)類(lèi)型。
順便說(shuō)一句:關(guān)于此問(wèn)題的診斷已經(jīng)相當(dāng)不錯(cuò)。如果您嘗試addElement在Xcode 9中調(diào)用上述代碼,則會(huì)得到以下信息:
Cannot pass immutable value as inout argument: implicit conversion from '[Int]' to '[Any]' requires a temporary
這告訴您的是,Swift愿意將[Int]您要求的位置[Any]作為數(shù)組的特殊情況傳遞給您(盡管這種特殊待遇并未擴(kuò)展到其他泛型類(lèi)型)。但是它只能通過(guò)制作數(shù)組的臨時(shí)(不可變)副本來(lái)允許它。(這是另一個(gè)很難解釋Swift性能的示例。在其他語(yǔ)言中看起來(lái)像“廣播”的情況下,Swift可能會(huì)復(fù)制一個(gè)副本?;蛘呖赡懿粫?huì)復(fù)制。很難確定。)

TA貢獻(xiàn)1911條經(jīng)驗(yàn) 獲得超7個(gè)贊
解決此問(wèn)題的一種方法是向其中添加一個(gè)初始化程序,Thing并創(chuàng)建一個(gè)Thing<Flavor>保存Vanilla對(duì)象的對(duì)象。
它看起來(lái)像:
class Thing<T> {
init(thing : T) {
}
}
protocol Flavor {}
class Vanilla: Flavor {}
var dict = [String:Thing<Flavor>]()
dict["foo"] = Thing<Flavor>(thing: Vanilla())

TA貢獻(xiàn)1844條經(jīng)驗(yàn) 獲得超8個(gè)贊
請(qǐng)注意,您的反例inout
僅說(shuō)明了作為inout
參數(shù)傳遞的變量必須具有不變性(inout
讀和寫(xiě)該變量都可以)。并不是因?yàn)槿我夥盒投际遣蛔兊模▽?shí)際上,正如您在編輯中強(qiáng)調(diào)的那樣,這Array
是一種特殊情況- [Int]
確實(shí)是的子類(lèi)型[Any]
,但是您的示例仍然正確地是非法的)。您也可以看到根本沒(méi)有泛型,例如func foo(a: inout Any, b: Any) { a = b }; var i = 1; foo(a: &i, b: "Stuff")
,這是非法的。
- 3 回答
- 0 關(guān)注
- 820 瀏覽
添加回答
舉報(bào)