4

I have a protocol called SomeProtocol

I want to create a function that get an object that confirms to this protocol, and add it to an array.

then I have another function that remove an object from this array.

var allObjs = [SomeProtocol]()

func addObj<T: AnyObject where T: SomeProtocol>(obj: T) {
    allObjs.append(obj)
}

func removeObj<T: AnyObject where T: SomeProtocol>(obj: T) {
    for someObj in allObjs {
        if someObj == obj { // compile time error -> Binary operator '==' cannot be applied to operands of type 'SomeProtocol' and 'T'

        }
    }
}  

This code will cause a compile time error "Binary operator '==' cannot be applied to operands of type 'SomeProtocol' and 'T'"

not sure how can i fix that, both object where defined as AnyObject who confirm to the SomeProtocol protocol, so what is the problem here?

Mario
  • 2,431
  • 6
  • 27
  • 34
  • The questions to ask yourself: what are you expecting `==` to do? Where would this ability to use `==` on two arbitrary `SomeProtocol` types come from? Have you defined a `==` operator that takes two `SomeProtocol`? Do you want _reference_ equality (`===` rather than `==`)? – Airspeed Velocity Jul 02 '15 at 11:10
  • yes i want a reference equality just to check if this is the same object, but === doesn't work as well – Mario Jul 02 '15 at 11:12
  • Possible duplicate of [Comparing two custom objects in swift](http://stackoverflow.com/questions/29942511/comparing-two-custom-objects-in-swift), and [this answer](http://stackoverflow.com/a/29943227/1187415) should solve your problem. – Martin R Jul 02 '15 at 11:17
  • See also [Find index of object in an array of type SomeProtocol](http://stackoverflow.com/questions/30344222/find-index-of-object-in-an-array-of-type-someprotocol). – Martin R Jul 02 '15 at 11:20

3 Answers3

4

For comparing two generics, you can declare the generics such that, types, that are capable to be in the place of your generic type, should conform to Comparable protocol.

struct Heap<T: Comparable>{
var heap = [T]()
}}

Now we will be able to do:-

if heap[parentIndex] < heap[childIndex] {
//Your code
}

How this works?

As we know, conforming to a protocol means implementing all the required methods in that protocol. Comparable protocol has got all the comparison methods as required parameters, and any type that is implementing Comparable will be able to do a comparison.

Happy coding using Generics.

Sebin Roy
  • 834
  • 9
  • 10
1

If you want reference equality, then you need to ensure SomeProtocol only applies to classes (since you can’t use reference equality on structs, as they’re value types):

protocol SomeProtocol: class { }

Now, only classes can implement SomeProtocol.

You don’t need generics to use reference equality now, just regular run-time polymorphism:

func removeObj(obj: SomeProtocol) {
    // since any SomeProtocol-conforming object
    // must be a class, you can now use ===
    if let idx = allObjs.indexOf({ $0 === obj}) {
        allObjs.removeAtIndex(idx)
    }
}
Airspeed Velocity
  • 40,491
  • 8
  • 113
  • 118
  • for some reason i can't call indexOf on my array – Mario Jul 02 '15 at 11:40
  • That’s a 2.0 feature, if you’re using 1.2 you still need to do it with a loop as in your original question. – Airspeed Velocity Jul 02 '15 at 11:44
  • can u pls give an example how to loop and remove object from the array? in objective c i used to store those objectsToRemove in an array and then call removeObjectsInArray: – Mario Jul 02 '15 at 12:07
  • That’s a separate question, accept this one (assuming it answers your question) and post a new one (though probably there is already one asking this) – Airspeed Velocity Jul 02 '15 at 12:25
0

The generic function must also conform to the Equatable protocol

vadian
  • 274,689
  • 30
  • 353
  • 361
  • Not quite as simple as that in this case – the array is of protocols rather than actual objects, so would need to equate two potentially different types both adhering to the same protocol. – Airspeed Velocity Jul 02 '15 at 10:57
  • should i define an array of AnyObject that confirm to the protocol? can i even do that? – Mario Jul 02 '15 at 11:13
  • No, you can’t do that, since `Equatable` has an associated type – it can only be used as a constraint, you can’t have an array of different `Equatable` types. – Airspeed Velocity Jul 02 '15 at 11:13