有沒有辦法給函數賦一個參數,該參數是函數變量的子類,參數是它的超類?這裏是我的意思的一個例子:函數類型中的swift子類
class ClassA {}
class subclassOfA:ClassA {}
func subclassToNil(argument:subclassOfA) ->(){}
var functionVariable:(ClassA->())
funcVar = subclassToNil
這引發了一個類型不兼容異常。
有沒有辦法給函數賦一個參數,該參數是函數變量的子類,參數是它的超類?這裏是我的意思的一個例子:函數類型中的swift子類
class ClassA {}
class subclassOfA:ClassA {}
func subclassToNil(argument:subclassOfA) ->(){}
var functionVariable:(ClassA->())
funcVar = subclassToNil
這引發了一個類型不兼容異常。
恐怕不是 - 你發現了「協變」和「反轉」。函數類型與它們的參數(參數)是不相容的,這意味着如果需要,您可以提供一個超類,但不是子類。與返回值另一方面,功能類型是協變,並可以返回子類如果您願意。
隨着一點點的思想,這些規則意義:
class ClassA {}
class SubclassOfA: ClassA {}
func subclassToNil(argument: SubclassOfA) ->()) {}
var functionVariable: (ClassA ->())
functionVariable = subclassToNil
functionVariable(ClassA()) //`subclassToNil` won't know what to do with this; kablooie!
但是:
class ClassParent {}
class ClassA: ClassParent {}
func subclassToNil(argument: ClassParent) ->()) {}
var functionVariable:(ClassA ->())
functionVariable = subclassToNil
functionVariable(ClassA()) //`ClassA()` is indeed a valid `ClassParent`, so we're fine.
所以它的安全使用是少具體參數。返回值的推理非常相似,從邏輯上看,您可以使用更多特定的。
這很有趣,因爲我已經嘗試了一個返回類型作爲子類的例子,正如你所說的,編譯器沒有抱怨。這個例子很清楚爲什麼因爲設置'subclassToNil'不會改變functionVariable的類型簽名! – chartman
這是行不通的。 'functionVariable()'可以用'ClassA'的一個實例調用,但是該函數需要一個* subclass *的實例作爲參數。 (它只會反過來工作。) –