2015-08-11 1 views
2

У меня есть класс, который должен быть установлен с переменной подкласса NSObject и который реализует определенный протокол.Что такое быстрый эквивалент NSObject <Protocol>?

protocol ProtoTest { 
    var foo: Int { get set } 
} 


class AClass: NSObject, ProtoTest { 
    var foo: Int = 3 
} 


class BClass: NSObject, ProtoTest { 
    var foo: Int = 4 
} 

class Consumer { 

    var protoInstance: ProtoTest? //Does not cary any information of the class just the protocol 
    var protoInstance2: protocol<NSObjectProtocol, ProtoTest>? 

    init(x: ProtoTest) { 
     self.protoInstance = x 
     self.protoInstance2 = nil 
    } 

    init(x: protocol<NSObjectProtocol, ProtoTest>) { 
     self.protoInstance2 = x 
     self.protoInstance = nil 
    } 

    func doSomething() { 
     if let x = protoInstance { 
      x.copy() //'ProtoTest' does not have a member named 'copy' 
     } 
     if let x = protoInstance2 { 
      x.copy() //protocol<NSObjectProtocol, ProtoTest> does not have a member named 'copy' 

     } 
    } 
} 

В приведенном выше примере никакие декларации переменной не будут работать. поскольку ни у кого из них нет знания базового класса?

Как это реализовать в быстром?

ответ

1

Вы можете сделать это несколькими способами. Во-первых, вы можете сделать Consumer родовое:

class Consumer<T: NSObject where T: Prototest> { 
    var protoInstance: T? 
    var protoInstance2: T? 
} 

Если вы сделаете это, то все ссылки на protoInstance или protoInstance2 унаследует от NSObject, и вы будете иметь возможность вызывать методы как .copy() непосредственно на объекте.

Если вы не хотите Consumer быть универсальным, вы можете применять ограничения на init методов с использованием основных параметров, например:

class Consumer { 
    // ... 
    init<T: NSObject where T: Prototest>(x: T) { 
     protoInstance = x 
    } 
} 

Если вы сделаете это, вы будете гарантированы, что protoInstance будет NSObject, но вам придется бросить в NSObject использовать любой из методов NSObject «s:

func doSomething() { 
    if let x = protoInstance as? NSObject { 
     x.copy() 
    } 
} 

Edit:

Обратите внимание, что я не был уверен, действительно ли вы хотели, чтобы protoInstance и protoInstance2 были разных типов. Я был немного неясным из вашего вопроса. Если вы хотите, чтобы они были разными типами, я могу добавить дополнительные предложения к этому ответу.

+0

Спасибо Roman, Таким образом, вы не думаете, есть способ обеспечить NSObject в объявлении переменной? –

+0

Можно определить переменную как «var protoInstance: NSObject?», а затем перевести на «Prototest», если вы хотите ее использовать. Но если вы хотите применить что свойство является и «NSObject' * и * a« Prototest », тогда вам придется использовать дженерики где-то ... –

+0

@EdwardAshak« Итак, вы не думаете, что есть способ принудительного применения NSObject ». Почему вы думаете, что вам нужно это сделать? – matt

2

обычный эквивалент NSObject<Protocol> в Свифт просто Protocol. Как правило, этот протокол объявляется как протокол класса, чтобы гарантировать, что он будет принят классом.

Если вы также нужны методы протокола NSObject (такой respondsToSelector:, а затем сделать протокол принять NSObjectProtocol.

Если проблема заключается в том, что просто вы хотите позвонить copy() и вы не можете убедить компилятор позволить вам сделать он, затем принять NSCopying, а также (или просто использовать respondsToSelector: и performSelector: обойти компилятор вообще).

 Смежные вопросы

  • Нет связанных вопросов^_^