如何获得泛型类的大小(计数)?

时间:2016-09-20 01:47:34

标签: ios swift generics

如何创建一个泛型类,我可以在其中获取项目的大小(或计数),无论它是Int,String等...

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
    }

}

我想这样做,所以我可以比较这样的项目:

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

更新 我现在遇到正常比较的问题。我收到了错误,&#34;二元运算符&#39; ==&#39;不能应用于&#39;任何&#39;类型的操作数。和&#39;任何?&#39; (又名&#39;协议&lt;&gt;&#39;)&#34;

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
}

我尝试实施自定义&#39; ==&#39;运算符以及节点比较的运算符

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

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

2 个答案:

答案 0 :(得分:1)

您只需要让您的Node类符合Equatable和Comparable,并将您的项类型更改为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
}

用法:

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

答案 1 :(得分:1)

我建议简单地定义一个NodeItem协议,该协议需要_count属性和Comparable一致性,允许符合类型实现自己的逻辑来定义他们想要节点的{{1}要定义。

count

然后,您可以将protocol NodeItem : Comparable { // It's prefixed with an underscore to indicate that it shouldn't be used directly // by anything other than Node (else it would be confusing for Int to have // a count property) var _count : Int { get } } // conform Int and String to NodeItem, allowing them to define _count extension String : NodeItem { var _count: Int { return characters.count } } extension Int : NodeItem { var _count: Int { return self } } 类“项目类型限制为此协议,并通过简单地返回Node的{​​{1}}来实施count

_count

item

这样做的好处是class Node<Item : NodeItem> { // I see no reason for item to be optional, as Node must be initialised with one. var item: Item var next: Node? init(item: Item, next:Node?) { self.item = item self.next = next } var count: Int { return item._count } } 的{​​{1}}属性是强类型的,允许编译器强制类型安全 - 例如阻止构造let one = Node(item: 1, next: nil) let two = Node(item: 2, next: nil) print(one.count < two.count) // true let str1 = Node(item: "moose", next: nil) let str2 = Node(item: "cow", next: nil) print(str1.count < str2.count) // false item类型未实现其自己的Node逻辑或不是Node的情况。此外,由于它不依赖于运行时类型转换,编译器将有更多的优化机会。

在实现搜索逻辑时,您可以直接将节点项等同,因为它们是强类型的。例如,Item类:

_count