0

This one has been bugging me for a while now. I'm not sure if I'm missing something, but shouldn't this work?

protocol IDIdentifiable { }

class A : IDIdentifiable {
    let id : Int
    init(id: Int) { self.id = id }
}

class B : IDIdentifiable {
    let id : Int
    init(id: Int) { self.id = id }
}

func findObjectById<T: IDIdentifiable>(objects: [T], id: Int) -> T {
    if let casted = objects as? [A] {
        return casted.filter{ $0.id == id }[0]
    }
}

The error happens when casting the objects parameter to an array of A-objects. The error says 'A' is not a subtype of 'T', which is obviously not the case.

It's really annoying since I would like to have a generic method that can handle arrays of objects of multiple classes the same way. I tried first without creating an extra protocol like IDIdentifiable, using switch-statements, but none of these approaches worked.

I'm happy for any suggestions!

matt
  • 515,959
  • 87
  • 875
  • 1,141
Yeehaw
  • 105
  • 2
  • 11
  • Isn't this the same as my question here? http://stackoverflow.com/questions/33112559/protocol-doesnt-conform-to-itself – matt Oct 16 '15 at 14:31
  • 1
    Stop saying "didn't work". That is meaningless. You have fixed the question by explaining that the issue is a compile error. That is what I was after. – matt Oct 16 '15 at 14:36
  • Very similar indeed. Strange nonetheless. – Yeehaw Oct 16 '15 at 14:36
  • 'A' is not a subtype of 'IDIdentifiable' Is correct. But IDIdentifiable Is a subtype of A. You can up-cast arrays but not downcast. – Sentry.co Jul 31 '16 at 17:22

1 Answers1

0

If you declare the protocol to require a variable id you don't need to cast the type in the generic method.

protocol IDIdentifiable {
  var id : Int { get set }
}

class A : IDIdentifiable {
  var id : Int
  init(id: Int) { self.id = id }
}

class B : IDIdentifiable {
  var id : Int
  init(id: Int) { self.id = id }
}

func findObjectById<T: IDIdentifiable>(objects: [T], id: Int) -> T {
    return objects.filter{ $0.id == id }[0]
}
vadian
  • 274,689
  • 30
  • 353
  • 361
  • That is true but it doesn't explain the issue with an array typed as a protocol. And what if this were about a property not defined by the protocol but defined only in class A? – matt Oct 16 '15 at 14:39
  • I will accept this answer, since it helped me resolve this particular issue for now. As @matt said though, it doesn't help with the general problem. – Yeehaw Oct 16 '15 at 14:45
  • I agree. You're right to accept it but we're not getting anywhere with _my_ problem. :) – matt Oct 16 '15 at 14:56
  • A personal statement: For me Swift is a language which encourages the developer to specify the types as narrow as possible and as generic as necessary rather than as generic as possible and as narrow as necessary ;-) – vadian Oct 16 '15 at 14:57