How to use a generic class without the type argume

2019-04-24 07:38发布

问题:

I want to encapsulate a generic object in another class without setting the generic type argument. I created a base Animal<T> class and defined other subclasses from it. Example:

public class Animal<T: YummyObject> {
    // Code
}

public class Dog: Animal<Bark> {
    // Code
}

public class Cat: Animal<Meow> {
    // Code
}

and defined an Animal property, without the type argument, in the UITableView extension bellow:

extension UITableView {
    private static var animal: Animal!

    func addAnimal(animal: Animal) {
        UITableView.animal = animal
    }
}

but I get the following compile error when doing so:

Reference to generic type Animal requires arguments in <...>.

This seems to work fine in Java. How can I accomplish the same thing in Swift as well?

回答1:

Swift doesn’t yet support wildcard-style generics like Java does (i.e., Animal<?>). As such, a common pattern is to define a type-erased superclass, protocol (or wrapper) to enable such usage instead. For instance:

public class AnyAnimal {
    /* non-generic methods */
}

and then use it as your superclass:

public class Animal<T: YummyObject>: AnyAnimal {
    ...
}

Finally, use AnyAnimal in your non-generic code instead:

private static var animal: AnyAnimal!

Examples in the Swift Standard Library. For a practical example, see the KeyPath, PartialKeyPath, and AnyKeyPath classes hierarchy. They follow the same pattern I outlined above. The Collections framework provides even further type-erasing examples, but using wrappers instead.