Generic classes and inheritance

I have a model object:

class Animal {
// ...
}

      

And subclasses:

class Dog: Animal {
// ...
}

class Cat: Animal {
// ...
}

      

Also I created a generic class

class AnimalController<T: Animal> {
      var animal: T? 
      func feed(animal: T) {
          let food = Food(T.self)
          animal.feed(food)
      }
}

      

This is the problem:

class MainViewController: UIViewController {
      var controller: AnimalController<Animal>?

    // MARK: - Lifecycle

    override func viewDidLoad() {
        super.viewDidLoad()

        // I want control a dog
        self.controller = AnimalController<Dog>()  // Error

        // I want control a cat
        self.controller = AnimalController<Cat>()  // Error
    }
}

      

How can I create a generic class that is compatible with both dogs and cats? Thank!

UPDATED Hamish will give me a solution linking the other two posts.

I have a model object:

class Animal {
// ...
}

      

And subclasses:

class Dog: Animal {
// ...
}

class Cat: Animal {
// ...
}

      

Also I created a generic class

class AnimalController<T> {
    var type: T

    init(type: T) {
        self.type = type
    }

    func feed() {
        if type is Animal.Type {
            let food = Food(type as! Animal.Type)
            animal.feed(food)
        }
    }
}

      

Now it works:

class MainViewController: UIViewController {
      var controller: AnimalController<Animal>?

    // MARK: - Lifecycle

    override func viewDidLoad() {
        super.viewDidLoad()

        // I want control a dog
        self.controller = AnimalController<Dog>()  // Works!
        self.controller = AnimalController<Cat>()  // Works!
    }
}

      

+3


source to share


3 answers


Swift is a strong language. You have already declared your property controller

, and you cannot change its type, but this is perfectly fine as Swift supports the generic paradigm that allows objects to be stored in a property with a generic superclass.



0


source


This is similar to the case where inheritance should be used instead of generics.

class AnimalController {
    // basic animal control tasks
}


class CatController: AnimalController {
    // specialized controller just for cats
}
class DogController: AnimalController {
    // ...
}

      

Then you could just write



class MainViewController: UIViewController {
    var animalController: AnimalController

    override func viewDidLoad() {
        super.viewDidLoad()

        // I want control a dog
        self.controller = DogController()

        // I want control a cat
        self.controller = CatController()
    }
}

      

Working with generics can lead to problems in this case, as the Swift compiler resolves generic types and replaces them with specific types (which is not possible unless you create an entire generic view controller, but it will work well with an interface builder)

0


source


In your example, there is no need to create a AnimalController

generic class. It can just have methods that work for Animals

, and they will work for Dog

as well as Cat

through inheritance.

class Animals {
    // ...
}

class Dog: Animals {
    // ...
}

class Cat: Animals {
    // ...
}

class AnimalController {
    // methods to control any kind of animals
    var animal: Animals? // Will take both cats and dogs
    func feed(animal: Animals) {
        // Will take both cats and dogs
    }
}

class MainViewController: UIViewController {
    var controller: AnimalController?

    // MARK: - Lifecycle

    override func viewDidLoad() {
        super.viewDidLoad()

        // I want control a dog or a cat
        self.controller = AnimalController()

        let cat = Cat()
        controller?.animal = cat
        controller?.feed(animal: cat)

        let dog = Dog()
        controller?.animal = dog
        controller?.feed(animal: dog)
    }
}

      

(updated)

Even after your changes, I see no need for generics:

class Animal {
    // ...
    func feed(_ food: Food){
        // feed the animal or maybe throw an error
        // if subclasses must implement
    }
}

class Dog: Animal {
    // ...
    override func feed(_ food: Food) {
        // feed a cat
    }
}

class Cat: Animal {
    // ...
    override func feed(_ food: Food) {
        // feed a dog
    }
}

class Food {
    init(_ animalType: Animal.Type) {
        // Make food
    }
}

class AnimalController {
    // methods to control any kind of animals
    var animal: Animal? // Will take both cats and dogs
    func feed(animal: Animal) {
        // Will take both cats and dogs
        let food = Food(type(of: animal))
        animal.feed(food)
    }
}

class MainViewController: UIViewController {
    var controller: AnimalController?

    // MARK: - Lifecycle

    override func viewDidLoad() {
        super.viewDidLoad()

        // I want control a dog or a cat
        self.controller = AnimalController()

        let cat = Cat()
        controller?.animal = cat
        controller?.feed(animal: cat)

        let dog = Dog()
        controller?.animal = dog
        controller?.feed(animal: dog)
    }
}

      

0


source







All Articles