Reputation: 182
Is there a way to assign a function with a parameter that is a subclass to a function variable with a parameter that is its superclass? Here is an example of what I mean:
class ClassA {}
class subclassOfA:ClassA {}
func subclassToNil(argument:subclassOfA) -> (){}
var functionVariable:(ClassA->())
funcVar = subclassToNil
This raises a type incompatibility exception.
Upvotes: 1
Views: 509
Reputation: 14824
I'm afraid not--you've discovered "covariance" and "contravariance". Function types are contravariant with their parameters (arguments), which means you could supply a superclass if you wanted, but not a subclass. With return values on the other hand, function types are are covariant and could return a subclass if you'd like.
With a little thought, these rules make sense:
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!
However:
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.
So it's safe to use parameters that are less specific. The reasoning for return values is very similar, and you'll see that logically, you can use ones that are more specific.
Upvotes: 2