2015-03-15 13 views
7

Mam zajęcia z delegatem. Tworzę podklasę, która również ma delegata. Chciałem niech protokół wykorzystywany do drugiego delegata przedłużyć protokół używany przez pierwszego delegata:Dziedziczenie protokołów + delegaci w Swift

protocol MySuperClassProtocol { 
    func foo() 
} 

class MySuperClass { 
    var delegate:MySuperClassProtocol? 
} 

protocol MySubClassProtocol:MySuperClassProtocol { 
    func bar() 
} 

class MySubClass: MySuperClass { 
    override var delegate:MySubClassProtocol? // compiler error - "cannot override..." 

    func test() { 
     delegate?.foo() 
     delegate?.bar() 
    } 
} 

class UserClass:MySubClassProtocol { 
    func foo() { 
     println("foo!") 
    } 
    func bar() { 
     println("bar") 
    } 
} 

Czy istnieje sposób, aby rozwiązać ten problem? Jedynym możliwym rozwiązaniem jest uniezależnienie dwóch protokołów od siebie i użycie różnych nazw. Tak:

protocol MySuperClassProtocol { 
    func foo() 
} 

class MySuperClass { 
    var mySuperClassDelegate:MySuperClassProtocol? 
} 

protocol MySubClassProtocol { 
    func bar() 
} 

class MySubClass: MySuperClass { 
    var mySubClassDelegate:MySubClassProtocol? 

    func test() { 
     mySuperClassDelegate?.foo() 
     mySubClassDelegate?.bar() 
    } 
} 

class UserClass:MySuperClassProtocol, MySubClassProtocol { 
    func foo() { 
     println("foo!") 
    } 
    func bar() { 
     println("bar") 
    } 
} 

Ale wygląda to nieco dziwne + nie pozwoli mi korzystać nazewnictwo dla delegate- „delegata”.

+0

Dlaczego potrzebujesz protokołu Super Class i Super Class? –

+1

Ponieważ umieszczam wspólną funkcjonalność wielu klas w super klasie i jest tam również "wspólny delegat". – Ixx

Odpowiedz

0

Możesz to zrobić w inny sposób, możesz dodać zmienną delegate w podklasie i użyć jej do uzyskania dostępu do SuperClassProtocol również przy użyciu delegate?.foo().

protocol MySuperClassProtocol { 
    func foo() 
} 

class MySuperClass { 
    //var delegate:MySuperClassProtocol? 
} 

protocol MySubClassProtocol:MySuperClassProtocol { 
    func bar() 
} 

class MySubClass: MySuperClass { 
    var delegate:MySubClassProtocol? 

    func test() { 
     delegate?.foo() 
     delegate?.bar() 
    } 
} 

class UserClass:MySubClassProtocol { 
    func foo() { 
     println("foo!") 
    } 
    func bar() { 
     println("bar") 
    } 
} 

Ale problem w tym, że nigdy nie można używać MySuperClassProtocol niezależnie chyba utworzyć nową podklasę MySuperClass tylko do deklarowania delegate zmienną.

+0

Nie to, czego potrzebuję ... pomysł posiadania super-klasy delegata jest taki, że każda podklasa go posiada. W tym celu musiałbym zadeklarować delegata w każdej podklasie. – Ixx

+0

@ixx: Więc co? Nie można wywołać metody podklasy za pomocą wskaźnika klasy bazowej, chyba że umieści się ją w klasie bazowej (zadeklaruj ją w klasie bazowej lub właściwości baseclass). To jest koncepcja czystego oopa. Nie ma innej drogi niż 1 zdefiniowana w twoim pytaniu i 1, o której tutaj wspomniałem. Nie można tego zrobić również w obiektywnym c. Szukasz czegoś, co nie jest nawet możliwe. –

+0

cóż, tego właśnie szukam, sposób na posiadanie podstawowego delegata w klasie bazowej, więc mogę go wywołać z dowolnego miejsca. Obawiam się, że jedyną drogą jest to, o co pytam. "szukasz czegoś, co nie jest nawet możliwe" - tego nie wiesz, gdy zadajesz pytanie;) – Ixx

5

starałem się znaleźć idealne rozwiązanie do tego przez jakiś czas, ale nie mógł wymyślić nic lepszego w tym:

protocol BaseDelegateProtocol: class { } 

class BaseDelegate: BaseDelegateProtocol { } 

class BaseActor { 
    weak var delegate: BaseDelegate? = nil 
} 

// MARK: - 

protocol ConcreteDelegateProtocol: class { 
    func doSomething() 
} 

class ConcreteDelegate: BaseDelegate, ConcreteDelegateProtocol { 
    func doSomething() { 
     // Do something 
    } 
} 

class ConcreteActor: BaseActor { 
    private weak var concreteDelegate: ConcreteDelegateProtocol? = nil 

    override var delegate: BaseDelegate? { 
     didSet { 
      concreteDelegate = delegate as? ConcreteDelegateProtocol 
     } 
    } 
} 

powyżej działa w Xcode 7/Swift 2.

  • Ten wzorzec umożliwia przyjmowanie coraz większej liczby protokołów po przejściu w dół po odziedziczeniu z BaseDelegate.
  • Nie ma potrzeby dziedziczenia protokołów od siebie nawzajem, co pomaga w utrzymaniu izolacji.
  • didSet obserwator na delegate nieruchomość jest wywoływana automatycznie dla superklas, więc nie ma potrzeby, aby zadzwonić super.<blah> jawnie i bez ryzyka „zapomnieć” robi tak
  • właściwości delegata betonowe mogą być przechowywane prywatne na każdym poziomie dziedziczenia, a tym samym obniżając nieład.
1

Przepraszamy za necroposting, jedynym rozwiązaniem znalazłem to:

protocol SuperClassDelegate { 
    func first_method() 
} 

class SuperClass { 
    var delegate: SuperClassDelegate? 

    func do_something() { 
     delegate?.first_method() 
    } 
} 

protocol SubClassDelegate: SuperClassDelegate { 
    func second_method() 
} 

class SubClass: SuperClass { 
    private var subDelegate: SubClassDelegate? 
    override var delegate: SuperClassDelegate? { 
     get { return self.subDelegate } 
     set { self.subDelegate = newValue as! SubClassDelegate? } 
    } 

    //override func do_something() { 
    // super.do_something() 
    // subDelegate?.second_method() 
    //} 

    func do_something_other() { 
     //subDelegate?.first_method() 
     self.do_something() 
     subDelegate?.second_method() 
    } 
} 

class InheritanceAndDelegation: SubClassDelegate { 
    let obj = SubClass() 

    init() { 
     obj.delegate = self 
    } 

    internal func first_method() { 
     print("Hello from SuperClass") 
    } 

    internal func second_method() { 
     print("Hello from SubClass") 
    } 

    func check() { 
     obj.do_something_other() 
    } 
} 

let inheritanceAndDelegation = InheritanceAndDelegation() 
inheritanceAndDelegation.check() 
//prints: 
//Hello from SuperClass 
//Hello from SubClass 

skomentowane kod działa zbyt. Mam nadzieję, że przyda się komuś.