2015-11-17 4 views
3

Можно ли ограничивать общий тип приема протокола в Swift?Общее ограничение для любого протокола в Swift

Я реализовал оболочку, чтобы иметь слабый список объектов, и мне нужно расширить это до протоколов.

protocol Incrementable: class { 
    func inc() 
} 

class Counter: Incrementable { 
    var n: Int = 0 

    func inc() { 
     n += 1 
    } 
} 

struct Weak<T: AnyObject> { 
    weak var value : T? 
    init (value: T?) 
    { 
     self.value = value 
    } 
} 

var cnt: Counter? = Counter() 

let counters : [Weak<Counter>] = [Weak(value: cnt), Weak(value: Counter())] 

for counter in counters 
{ 
    counter.value?.inc() 
} 

Теперь, если я хочу, чтобы хранить любой объект, который реализует Incrementable я должен использовать AnyObject и это не очень типа безопасны, а также включает в себя as? литье

let counters : [Weak<AnyObject>] = [Weak(value: cnt), Weak(value: Counter())] 

for counter in counters 
{ 
    (counter.value as? Incrementable)?.inc() 
} 

И код, который я хотел бы иметь бы быть

let counters: [Weak<Incrementable>] = [Weak(value: cnt), Weak(value: Counter())] 

for counter in counters 
{ 
    counter.value?.inc() 
} 

конечно, приведенный выше код не может быть скомпилирован и терпит неудачу с:

Использование «Incrementable» в качестве конкретного типа, соответствующего протокола «AnyObject» не поддерживается

Можно ли написать Weak обертку, чтобы он мог принимать и хранить слабые ссылки на протокол?


Хотя основная причина моей проблемы такая же, как и в Using as a concrete type conforming to protocol AnyObject is not supported, что вопрос имеет дело с хэш-таблицей и мне нужно решение со списками, что позволяет повторяющиеся записи.

+1

Возможная Дубликат [Использование в качестве конкретного типа, соответствующего протокола AnyObject не поддерживается] (http://stackoverflow.com/questions/32807948/using-as-a-concrete-type-conforming-to- protocol-anyobject-is-not-supported) –

+0

@ BartłomiejSemańczyk Я не думаю, что это дубликат, но с помощью этого Q & A мне удалось найти лучшее решение для моей проблемы, и я разместил его как ответ. Однако, если у кого-то есть лучшие предложения/решения, я все уши. –

+0

Почему 'AnyObject' недостаточно? Единственным другим вариантом являются структуры, и я не совсем уверен, как слабые ссылки должны работать с структурами? – Sulthan

ответ

1

answer указал мне в правильном направлении, и я смог найти следующее решение для реализации слабого списка ссылок протокола, который позволяет дублировать и nil (удобство) записей.

struct Weak<T> 
{ 
    weak var value: AnyObject? 
    init (value: T?) 
    { 
     if value != nil 
     { 
      guard value is AnyObject else { fatalError("Object (\(value)) should be subclass of AnyObject") } 
      self.value = value as? AnyObject 
     } 
    } 
} 

class WeakList<T>: SequenceType 
{ 
    var items : [Weak<T>] = [] 

    func add(item: T?) 
    { 
     items.append(Weak(value: item)) 
    } 

    func generate() -> AnyGenerator<T> 
    { 
     var nextIndex = items.count - 1 

     return anyGenerator 
     { 
      while nextIndex >= 0 
      { 
       let item = self.items[nextIndex--] 
       if item.value != nil 
       { 
        return item.value as? T 
       } 
      } 
      return nil 
     } 
    } 
} 

let incrementables = WeakList<Incrementable>() 

incrementables.add(Counter()) 
incrementables.add(cnt) 
incrementables.add(nil) 
incrementables.add(Counter()) 
incrementables.add(cnt) 

for counter in incrementables 
{ 
    counter.inc() 
}