user3353890 user3353890 - 2 months ago 5
iOS Question

How do I get the size (count) of a generic type class?

How do I create a generic class where I can get the size (or count) of an item regardless of whether it is an Int, String, etc...

class Node<T: Equatable> {

var item: T? = nil
var next: Node? = nil

init(item:T, node:Node?) {
self.item = item
self.next = node
}

var count:Int { <-------------- this is what I need to fix
return item.count
}

}


I want to do this so I can compare items like this:

let one = Node<Int>(item:1, node:nil)
let two = Node<Int>(item:2, node:nil)

return one.count < two.count <--------- should return true

let str1 = Node<String>(item:"moose", node:nil)
let str2 = Node<String>(item:"cow", node:nil)

return str1.count < str2.count <------- should return false


Update
I'm running into an issue with normal comparisons now. I get the error, "binary operator '==' cannot be applied to operands of type 'Any' and 'Any?' (aka 'protocol <>')"

func search(item:Any) -> Bool {

var current:Node? = self.head
var found = false

while current != nil && found != true {
if current?.item == item { <---------this is the error line
found = true
} else {
current = current?.next
}
}

return found
}


I tried implementing a custom '==' operator in addition to the one for Node comparisons

func ==(lhs: Node, rhs: Node) -> Bool {
return lhs.count == rhs.count
}

func ==(lhs: Any, rhs: Any) -> Bool {
return lhs == rhs
}

Answer

You just need to make your Node class conform to Equatable and Comparable, and change your item type to Any?:

class Node: Equatable, Comparable {

    var item: Any? = nil
    var next: Node? = nil

    init(item: Any?, node: Node?) {
        self.item = item
        self.next = node
    }
    var count: Int {
        // the trick is here, just conditionally casting to Int or String and return its Int value or the string characters count.
        if let val = item as? Int {
            return val
        }
        if let str = item as? String {
            return str.characters.count
        }
        return 0
    }
}

func ==(lhs: Node, rhs: Node) -> Bool {
    return lhs.count == rhs.count
}

func <(lhs: Node, rhs: Node) -> Bool {
    return lhs.count < rhs.count
}

Usage:

let nodeOne = Node(item:1, node:nil)
let nodeTwo = Node(item:2, node:nil)

 print(nodeOne < nodeTwo) // true

let nodeStr1 = Node(item:"moose", node:nil)
let nodeStr2 = Node(item:"cow", node:nil)

print( nodeStr1 < nodeStr2)  //  false