3

I am trying to do this:

protocol Fly {
}

class Bird: Fly {
}

func fetch<T: Fly>(model: T) {
    print("Done")
}

let bird: Fly = Bird()
fetch(model: bird)

However I get this error:

Cannot invoke 'fetch' with an argument list of type '(model: Fly)'

I set let bird: Fly = Bird() to be of type Fly, shouldn't it work since the function fetch takes any object that conforms to that protocol?

Any thoughts?

Vadim Kotov
  • 8,084
  • 8
  • 48
  • 62
JEL
  • 1,540
  • 4
  • 23
  • 51
  • If you are using protocol the syntax to do this is `func fetch(model: T) where T: Fly`. What you have typed is for subclassing I believe. But still it shows same error. – adev Aug 03 '17 at 05:22
  • @adev Thanks for pointing that out! Yeah still same error thought : ( – JEL Aug 03 '17 at 05:24
  • Any reason why you are not doing this -> `func fetch(model: Fly)` That will work fine, – adev Aug 03 '17 at 05:24
  • I will be using a library and might need to combine this function with it (unless not necessary but not sure at the moment). Wanted to see ideas as to what I'm doing wrong since I don't have experience with generics – JEL Aug 03 '17 at 05:26

2 Answers2

5

You are creating with Fly object with Bird instance

Replace code

protocol Fly {
}

class Bird: Fly {
}

func fetch<T: Fly>(model: T) {
    print("Done")
}

let bird: Bird = Bird() // Here is a problem 
fetch(model: bird)
Prashant Tukadiya
  • 15,838
  • 4
  • 62
  • 98
  • 2
    I know about that, but why can't I have this `let bird: Fly = Bird()` and pass that into the function if the function accepts any instance that conforms to `Fly`? – JEL Aug 03 '17 at 05:06
  • 1
    `Fly` Protocol doesn't confirm `Fly` it self . `Bird` does – Prashant Tukadiya Aug 03 '17 at 05:08
  • Oh that makes sense. Is there a way then to make the function `fetch` accept any type of type `Fly`? Or that doesn't make sense - not sure? – JEL Aug 03 '17 at 05:10
  • You can pass any class object that confirms protocol `Fly` as argument. – Prashant Tukadiya Aug 03 '17 at 05:11
  • 2
    `let bird: Fly = Bird()` is perfectly fine. I don't think that is the issue here. – adev Aug 03 '17 at 05:12
  • I just tried following and it works fine. `protocol Fly { func done() } class Bird: Fly { func done() { print("done") } } let bird: Fly = Bird() bird.done()` – adev Aug 03 '17 at 05:13
  • @adev I need to pass `Bird` into the function `func fetch(model: T)` which you are not doing – JEL Aug 03 '17 at 05:14
  • @adev In this case `func fetch(model: T)` is not part of protocol. – Prashant Tukadiya Aug 03 '17 at 05:15
  • @JEL, I was just showing `let bird: Fly = Bird()` is fine to do. I know this is not your case. So issue is not with that. My understanding is `func fetch(model: T)` accepts only if `Bird` is subclass of `Fly`. Not if it is implemented from protocol. – adev Aug 03 '17 at 05:16
  • @adev Oh ok, yeah I'm aware that is ok - thank you for mentioning too – JEL Aug 03 '17 at 05:17
2

I set let bird: Fly = Bird() to be of type Fly, shouldn't it work since the function fetch takes any object that conforms to that protocol?

The overload resolution of the fetch(model: bird) call is done statically at compile time. The bird instance has been explicitly annotated to be of type Fly (which happens to be a protocol which can hold, dynamically, instances conforming to it). Since protocols doesn't conform to themselves, a call to fetch(model: bird) will not be eligable to use the constrained generic method func fetch<T: Fly>(model: T), since the type of bird, namely Fly, does not fulfill the type constraint T: Fly.

dfrib
  • 70,367
  • 12
  • 127
  • 192