Swift: Method Overriding in Parameterized Class

Swift: Method overriding in parameterized class

It has nothing at all to do with the generics (what you call "parameterized"). It has to do with how one function type is substitutable for another in Swift. The rules is that function types are contravariant with respect to their parameter types.

To see this more clearly, it will help to throw away all the misleading generic stuff and the override stuff, and instead concentrate directly on the business of substituting one function type for another:

class A {}
class B:A {}
class C:B {}

func fA (x:A) {}
func fB (x:B) {}
func fC (x:C) {}

func f(_ fparam : B -> Void) {}

let result1 = f(fB) // ok
let result2 = f(fA) // ok!
// let result3 = f(fC) // not ok

We are expected to pass to the function f as its first parameter a function of type B -> Void, but a function of type A -> Void is acceptable instead, where A is superclass of B.

But a function of type C -> Void is not acceptable, where C is subclass of B. Functions are contravariant, not covariant, on their parameter types.

Swift, can I override a method with a more specific derived parameter type

Since PlaingCard inherits from Card you are not permitted to override the method in this way.

Consider what would happen if you tried to call match with an instance of PlayingCard. Which of the two methods would it call? It would be ambiguous and so is not allowed.

In this case one solution is to change the name of the method that takes the more specific type. e.g.

 func matchPlayingCard(othercards : [PlayingCard]) ->  Int {
return 2
}

How can I override a function with various inherited arguments (Swift)

Correct answer depends on generics:

class ItemA {
var valueA: String?
func setValueA(_ value: String?) {
valueA = value
}
}

class ItemB: ItemA {
var valueB: String?
func setValueB(_ value: String?) {
valueB = value
}
}

// Analog of the abstract class
class ClassA {
func setValues<T : ItemA>(_ item: T) {
item.setValueA("valueA")
getValues(item) // call getValues from ClassB
}
func getValues(_ item: ItemA) {
abort()
}
}

class ClassB: ClassA {
override func setValues<T : ItemB>(_ item: T) {
// item have type itemB, but extends ItemA
item.setValueB("valueB")
super.setValues(item)
}
override func getValues(_ item: ItemA) {
let item = item as! ItemB
let array = [item.valueA, item.valueB]
print(array)
}
}

Check it! If you want to print non-optional values, unwrap them.

    let itemB = ItemB()
ClassB().setValues(itemB)
// print ["valueA", "valueB"]

Swift - class method which must be overridden by subclass

You have two options:

1. Use a Protocol

Define the superclass as a Protocol instead of a Class

Pro: Compile time check for if each "subclass" (not an actual subclass) implements the required method(s)

Con: The "superclass" (protocol) cannot implement methods or properties

2. Assert in the super version of the method

Example:

class SuperClass {
func someFunc() {
fatalError("Must Override")
}
}

class Subclass : SuperClass {
override func someFunc() {
}
}

Pro: Can implement methods and properties in superclass

Con: No compile time check

How does swift pass along override method calls on casted inherited classes?

Am I doing something wrong?

Nope!

If not, is this the intended behavior of swift?

Yes, this is called polymorphism.

If so, then how on earth could you call the parent classes implementation of an overridden method?

You can't, and you shouldn't be able to.

Consider this example:

class Human {
func eat() {
print("I just ate a well rounded meal of veggies, meat, potatoes and of course, desert.")
}
}

class Vegetarian: Human {
override func eat() {
print("I just ate a meal of veggies, tofu, and desert. No meat!")
}
}

If this behaved as you expected, then this code:

let human = Vegetarian() as Human
human.eat()

...would cause a vegetarian to eat meat. They certainly won't be too happy about that.

There are MANY cases in which a subclass requires a different implementation (method) for a particular message (method call) than what the superclass provides. In such a case, giving the ability for consumers of the class to call the superclass method can lead the object into an inconsistent state, as you've violated the design it's supposed to work under.

Your second test, in fact, demonstrates one of the main use cases of polymorphism. You don't quite the effect here because test() doesn't do much of importance. Consider that these animal classes represented entities that could be draw on the screen. The procedure for drawing a cat would be very different from drawing a dog. Now what if I have a scene with multiple cats, dogs, horses, and honey badgers? It would be awfully inconvenient to need an [Cat], [Dog], [Horse], and [HoneyBadger], and separately iterate all of them to call .draw() on each of them. Instead, polymorphism allows me to store an array of [Animal], a common superclass to all of the animals I want to draw. Animal defines a draw() method that doesn't do much, but the fact that it's there guarantees me that I can call draw on any animal. My Cat, Dog, etc. all override the Animal definition of draw(), and provide their own implementation. When I iterate over my array and tell all my animals to draw themselves, they act with their own definition of draw().

In the previous example, polymorphism brought convenience. Here's an example that demonstrates functionality you couldn't otherwise achieve. Consider that my user can click on animals, and drag them around. For me to know which animal to move upon dragging, I need to know which animal was selected. I would do this by having a member variable of my scene, defined as let selectedAnimal: Animal?. Everytime my user clicks on an animal, I set selectedAnimal to the correct animal instance. Everytime they deselect, I set selectedAnimal back to nil. Upon dragging, I can call selectedAnimal?.moveTo(mouseX, mouseY). the moveTo call might be defined differently for Horse (which gallops), Dog (which runs on all 4s), and Cat (which sits around being a lazy ). Without polymorphism, there would be no way for me to be able to store a variable of an unknown (at compile time) concrete time. Polymorphism lets me store my animals as just Animal, knowing that whatever messages I send (methods I call) will be executed by the most appropriate override.



Related Topics



Leave a reply



Submit