2016-09-20 1 views
1

...ジェネリック型クラスのサイズ(カウント)を取得するにはどうすればよいですか?私は関係なく、それがint、文字列、などであるかどうかの項目のサイズを取得(またはカウント)できる汎用的なクラスを作成するにはどうすればよい

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 

更新 :このような項目を比較することができます。私はエラーを取得します。 "バイナリ演算子 '=='は 'Any'と 'Any?'型のオペランドには適用できません。 (別名「プロトコル<>」)」

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 
} 

私はあなたがちょうどあなたのNodeクラスが準拠するために必要なノードの比較

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

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

答えて

1

のために1に加えて、カスタム 『==』演算子を実装してみましたEquatableへと匹敵する、とあなたの項目タイプはどれに変更?:

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 
+0

私は1つの問題に取り組んでいますが、これは素晴らしい回答です。私はプログラム内の伝統的な方法で '=='演算子を使用していますが、エラーが発生し続けます: "2進演算子== 'は、' Any 'および' Any? '型のオペランドには適用できません。 (別名 'protocol <>')。 – user3353890

+0

たとえば、 "Node.item == item"を比較しようとする場合もあります。ここで私は今問題に取り組んでいるところです – user3353890

+0

私はあなたをさらに助けることはできませんあなたは完全なコードを表示しない場合 –

1

私は適合するタイプは、彼らが、ノードのcountになりたい方法を定義するための独自のロジックを実装することができ、単に_count財産とComparable適合性を必要とNodeItemプロトコルを定義助言します定義された。

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クラスのアイテムの種類を制限し、単にitem_countを返すことでcountを実装することができます

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 
    } 
} 

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 

このようにすることの利点は、コンパイラはNodeのタイプが_countのロジックを実装していない場合、またはComparableでない場合など、型の安全性を強制することができます。また、ランタイム型キャストに依存しないため、コンパイラは最適化の機会を増やすことになります。

検索ロジックの実装に関しては、厳密に型指定されているので、単純にノード項目を直接照合することができます。たとえば、LinkedList<Item>クラス:

class LinkedList<Item : NodeItem> { 

    let head : Node<Item> 

    init(head: Node<Item>) { 
     self.head = head 
    } 

    func search(item: Item) -> Bool { 

     var current : Node? = head 

     while current != nil { 
      if current?.item == item { 
       return true 
      } 
      current = current?.next 
     } 
     return false 
    } 
} 
関連する問題