如何创建一个泛型类,我可以在其中获取项目的大小(或计数),无论它是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
}
答案 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