2014-06-24 2 views
4

프로토콜을 준수하도록 확장을 제네릭 형식에 적용하는 방법이 있습니까?이 확장은 제네릭 형식의 특정 특수화에만 유효합니다.일반 유형의 일부 특수화에만 확장을 적용하는 방법은 무엇입니까?

예를 들어, 상기 프로토콜에 따르는 인스턴스에 포함 된 값의 빈도 카운트 사전 리턴이 프로토콜 고려해

// a type conforming to this protocol should return a dictionary 
// which counts the frequencies of values contained by the type instance 
protocol ConvertibleToFrequencyDictionary { 
    typealias ItemType 
    func dictionaryCountingFrequencies<ItemType:Hashable>() -> Dictionary<ItemType,Int> 
} 

을하기 때문에 사전에 키로서 기능한다 계산되는 값으로, 값 Hashable을 준수하는 유형이어야합니다. 이것은 일반 dictionaryCountingFrequencies 메소드의 정의에 대한 유형 제약 조건으로 표현됩니다. ("typealias"선언과 같은 연관된 유형에 유형 제약 조건을 직접 정의 할 수있는 방법이 없습니다.)

이제 프로토콜에 맞게이 확장을 Array로 간주합니다.

extension Array : ConvertibleToFrequencyDictionary { 
    typealias ItemType=Element 
    func dictionaryCountingFrequencies<ItemType:Hashable>() -> Dictionary<ItemType,Int> { 
    var valueToCount = Dictionary<ItemType,Int>() 
    for item in self { 
     if let existingCount = valueToCount[item] { 
     valueToCount.updateValue(value: existingCount + 1, forKey: item) 
     } else { 
     valueToCount.updateValue(value: 1, forKey: item) 
     } 
    } 
    return valueToCount; 
    } 
} 

이 값은 Array에 나타나는 모든 고유 값의 빈도를 반환해야합니다. 물론 이러한 값은 해시 가능해야하므로이 확장은 Array<T:Hashable>에 적용될 때만 작동해야합니다.

그러나 Int는 Hashable 임에도 불구하고 Array<Int>에서는 작동하지 않습니다.

왜 안 되니? 제네릭 형식의 확장을 작성하는 경우 해당 확장이 제네릭 형식의 모든 가능한 특수화에 대해 작동 할 수 있어야합니까?

답변

0

당신은 SequenceType 대신 Array, 이것은이 너무 적용하고 다음 whereElement의 종류를 제한하는 당신에게 더 많은 종류를 제공합니다 확장 할 수 있습니다.

  • Array 확장 where Element : SomeProtocol
  • SequenceType 확장 where Generator.Element : SomeProtocol

당신이 Int, 그것은 그 항목이 반드시 Hashable하지 아니었다 Hashable이었다 아니었다 가지고 있었던 문제를 필요로합니다. 이 예에서 항상 Hashable 이었으므로 ItemType으로 전송 한 것도 효과가있었습니다.

개인적으로 나는 이것을 위해 일반적인 것을 사용하지 않을 것입니다. Element는 배열에 저장할 수있는 모든 것을 이미 다룹니다. 그래서 그것을 타입 퍼지로 만들 필요가 없습니다.

extension SequenceType where Generator.Element : Hashable { 

    func dictionaryCountingFrequencies() -> Dictionary<Generator.Element,Int> { 
     var valueToCount = Dictionary<Generator.Element,Int>() 
     for item in self { 

      if let existingCount = valueToCount[item] { 
       valueToCount.updateValue(existingCount + 1, forKey: item) 
      } else { 
       valueToCount.updateValue(1, forKey: item) 
      } 
     } 
     return valueToCount; 
    } 
} 

let array = [1,2,3,4,5,1,1,1,2,3,3] 

let freqDict = array.dictionaryCountingFrequencies() 
// prints [5: 1, 2: 2, 3: 3, 1: 4, 4: 1] 
freqDict[5] 
// prints 1 
관련 문제