0

I need to compare a generic parameter when it's comparable, something like this:

class MyClass<Item> {

    var items: [[Items]]? {
        didSet {
            if Item is Equatable {
                print(oldValue == items)
            } else {
                print(false)
            }
        }
    }    

}

How can I achieve this?

I've also tried:

extension TableViewModel where Item: Equatable {

    func f() -> Bool {
        return true
    }

}

extension TableViewModel {

    func f() -> Bool {
        return false
    }

}

and adding an f() call to my didSet.

just to see if I can get the f() function from the Equatable extension to get called (had no success).

Rodrigo Ruiz
  • 4,248
  • 6
  • 43
  • 75

1 Answers1

0

Without beeing able to see your classes etc, i was able to produce what you want. You need to make sure the equatable methods are used properly however.

class Item {

}

class Items {

}

class Item2 : Item, Equatable {

    static func ==(_ lhs: Item2,_ rhs: Item2) -> Bool{
        return true
    }

    static func !=(_ lhs: Item2,_ rhs: Item2) -> Bool{
        return true
    }

}

class MyClass<Item> {

    var items: [[Items]]? {
        didSet {

        }
    }

}

extension MyClass where Item : Equatable {

    func f() {
        print("Hello")
    }

}

class TheClass : MyClass<Item2> {


    func someFunc() {
        super.f()
    }
}

let it = TheClass()

it.f() //prints : "Hello"

You just had to go an extra sub-classing step, by applying Equatable to the subclasses of Item (for those you wanted subclassed in the first place).

Explanation: you wanted a class which if subclassed for a generic Equatable type, could perform the method f(). This being said, you delegated Item as your top level type for conditionnally checking Equatable. That means since Item can or cannot be Equatable, you can only apply the protocol to a subclass of Item. If you applied Equatable straight to Item, you wouldn't have your problem. So to demonstrate this, i subclassed Item into Item2, and added Equatable to Item2. Thus creating a possibility for Item to exist in Equatable form.

Now you bring in MyClass<Item>, which is a seperate entity altogether, but which can adopt a type of class which inherits from or is Item altogether. But, since you specify that you only want subclasses of Item which are Equatable (ie: class Item2), you need to extend MyClass conditionaly for the types of Item which are Equatable as well. Hence the extension.

So finally, to demonstrate the whole subclassing logic, you need to subclass MyClass<Item>.. AGAIN.. but this time, by specifying this subclass to take Item2 as a generic type in order to explicitely declare that this subclass is equatable, because the only sub-generic Item type which is equatable is Item2 in your case.

Just by re-reading myself, it can be confusing.. But what you need to remember is that by applying generics, and by conforming them to protocols by CONDITIONAL EXTENSION, you allow for several different types of that same generic class to exist. Therefore, it increases the number of subclassing needed in order to adopt certain methods, in specific use-cases.

Also. As for your items : [[Item]]? didSet{} variable. I'm looking into it.. Howver i've found in this post a way to make it work with Equatable in Swift 4. I'm updating to Swift 4 as we speak to test out my code.

jlmurph
  • 1,050
  • 8
  • 17
  • I don't think I understood your example. the `f()` function is not even being called. – Rodrigo Ruiz Jul 31 '17 at 23:15
  • If you follow the structure i built, it is being called. However, i noticed i overlooked the didset.. is your items var really structured [[Item]] ? or is it a typo? – jlmurph Jul 31 '17 at 23:16
  • No typo, it really is `[[Item]]?`, and that's my issue. – Rodrigo Ruiz Jul 31 '17 at 23:39
  • And after your edit: I don't wanna specialize with `Items2`, I need to use the default swift `Array`. – Rodrigo Ruiz Jul 31 '17 at 23:40
  • Yeah, it makes sense now. Check the post i linked at the bottom of my update. Swift 4 allows you to add protocols by extension base on class parameters' protocols types. pretty neat. I've got to look at it some more before adding to my answer. – jlmurph Jul 31 '17 at 23:47