Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use Self as generic type

Tags:

generics

swift

Self can be used as the return type of a method:

func doSomething() -> Self {}

Is it somehow possible to use Self as a generic type like this?

func doSomething() -> Wrapper<Self> {}

Example

It would be nice if I could subclass ChristmasPresent and let it have a wrapped function that returns a WrappedPresent with the generic set to whatever the subclass was.

class ChristmasPresent {
    func wrapped() -> WrappedPresent<Self> {
        return WrappedPresent(present: self)
    }
}

class WrappedPresent<T: ChristmasPresent> {
    var present: T

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

class ToyCar: ChristmasPresent {}

let wrappedToyCar = ToyCar().wrapped() // Inferred to be: WrappedPresent<ToyCar> 
like image 433
Rengers Avatar asked Dec 16 '14 13:12

Rengers


People also ask

What do you mean by generic type?

A generic type is a generic class or interface that is parameterized over types.

What is a generic example?

The definition of generic is something without a brand name. An example of generic is the type of soap with a store's label that says "soap," but without a brand name. adjective.

How do you write a generic method?

All generic method declarations have a type parameter section delimited by angle brackets (< and >) that precedes the method's return type ( < E > in the next example). Each type parameter section contains one or more type parameters separated by commas.

How do you declare a generic type in a class?

The declaration of a generic class is almost the same as that of a non-generic class except the class name is followed by a type parameter section. The type parameter section of a generic class can have one or more type parameters separated by commas.


1 Answers

The most vexing paradox in Swift is this: "Swift prefers methods, but Swift's functions are more powerful." The Swift team knows that, and someday I am certain we will have powerful methods. But today is not that day. There are many things you'd like to express in methods that you cannot. Everything you want can be done easily with functions, however.

class ChristmasPresent {}

struct WrappedPresent<T: ChristmasPresent> {
    let present: T
}

func wrap<T:ChristmasPresent>(present: T) -> WrappedPresent<T> {
    return WrappedPresent(present: present);
}

class ToyCar: ChristmasPresent {}

let wrappedToyCar = wrap(ToyCar()) // Inferred to be: WrappedPresent<ToyCar>

Note that if your code did compile, you might still be quite surprised at the result. Swift custom types are not covariant, so a WrappedPresent<ToyCar> is not a subtype of WrappedPresent<ChristmasPresent>. So if you had an array of wrapped presents, you could not put a wrapped toycar in it. That could easily force you back to just using a fixed (non-type-parameterized) WrappedPresent type anyway, making the question moot. Generics and classes do not always mix as well as you might imagine in Swift.

If you have a practical example of a problem you'd want to solve with this, then I do recommend bringing it up on the dev forums. The Swift team is very responsive.

like image 128
Rob Napier Avatar answered Oct 12 '22 06:10

Rob Napier