Cannot convert value type ... when using generics and polymorphism in Swift 3

In my simplified example, I get an error: Cannot convert value of type 'Foo' to expected argument type BaseItem<Any>

But the class Foo

continues BaseItem<String>

.

This is some sample code:

class BaseItem<T> {
    var param: T?
}

class Foo: BaseItem<Int> {
}

func checkItem(item: BaseItem<Any>) -> Bool{
    return item.param  != nil;
}

      

I am getting an error when calling

checkItem(item: Foo())

      

What am I missing?

+3


source to share


4 answers


You need to define your function checkItem

in terms of generics:



func checkItem<T>(item: BaseItem<T>) -> Bool {
    return item.param != nil
 }

      

+1


source


The function signature checkItem

must be:, checkItem<T>(item: BaseItem<T>) -> Bool

as follows:

func checkItem<T>(item: BaseItem<T>) -> Bool {
    return item.param  != nil
}

      

Using:

checkItem(item: Foo()) // false

let myFoo = Foo()
myFoo.param = 0

checkItem(item: myFoo) // true

      



The reason why the compiler is complaining about

Cannot convert value of type Foo to expected type of BaseItem argument

is that you are trying to pass an BaseItem<Int>

instance as BaseItem<Any>

, which is invalid ( Any

data type not T

generic).

0


source


Make sure to define the checkItem function along with generics.

func checkItem<T>(item: BaseItem<T>) -> Bool {
     return item.param  != nil
}

      

0


source


The problem is that generics are invariant - consider if your function was checkItem(item:)

:

func checkItem(item: BaseItem<Any>) {
    item.param = "foo"
}

      

This would be illegal for BaseItem<Int>

, since you cannot assign an instance String

to a property Int?

, so it (instance Foo

) cannot be injected as BaseItem<Any>

.

The solution, as other answers have said, is to use a generic placeholder for the function:

func checkItem<T>(item: BaseItem<T>) -> Bool {
    return item.param != nil
}

      

Now, instead of saying that you are taking BaseItem<Any>

which has a param

type Any?

(it can be assigned a value of any type) - you are now saying that you are taking a BaseItem

with any particular placeholder type; which will be executed on the function call site.

The function implementation itself cannot make any assumptions about this type and does not allow assignment of an arbitrary value param

. The compiler will only allow assignment of a value to a type T

.

0


source







All Articles