mike
mike

Reputation: 2193

Swift cannot convert value of type which matches generic constraints

Given the following types

protocol AProtocol {}
protocol AnotherProtocol {}
class AClass: AProtocol, AnotherProtocol {}

I'm a bit confused why the following throws: "error: cannot convert value of type 'AClass' to specified type 'T'"

class generic<T> where T:AProtocol, T:AnotherProtocol {
    let prop: T = AClass()
}

But the following works fine:

class generic<T> where T: AProtocol, T: AnotherProtocol {
    let prop: T
    init(withProp prop: T) { self.prop = prop }
}

let instance = generic<AClass>(withProp: AClass())

Upvotes: 3

Views: 163

Answers (1)

Sweeper
Sweeper

Reputation: 272845

The generic parameters of your class are specified by the users of your class, not you.

You can't say that T has to be AClass like you did in your first code snippet that did not compile, because T is specified by the user. A user of your class might want something like:

let myObject = generic<BClass>()

where BClass also satisfies the constraints. Then what happens when the user tries to access the property? He will get an instance of AClass but T is actually BClass, so he should really be getting a BClass. See the contradiction here?

Regarding your comment:

In other words, it is not possible to refer to an implementation of the generic type(s) from inside the implementation of the generic class?

Exactly, because you don't know what those types are going to be. You can call methods declared in AProtocol and AnotherProtocol though. The generic constraints ensure that those methods exist.

If you want to make it work the way you want, you need what's called protocol composition:

var someProperty: (AProtocol & AnotherProtocol) = AClass()

Upvotes: 4

Related Questions