2015-01-15 3 views
1

Я пытаюсь реализовать не тривиальную (по крайней мере, для моего уровня) взаимосвязь между типами.Определить переменную, которая соответствует более чем одному протоколу/протоколу + суперкласс

класса A и B являются подклассами класса MySuperClass, и я позволяю им реализовать протокол «MyProtocol»

class MySuperclass {...} 

protocol MyProtocol { 
    func myProtocolMethod() 
} 

class A:MySuperclass, MyProtocol {...} 

class B:MySuperclass, MyProtocol {...} 

Мой класс «Контейнер» имеет переменную х, которая может быть либо экземпляром A или B

class Container {... var x:???? ....} 

Как может быть возможно из-за ???? моя проблема в том, что я бы хотел, чтобы я мог использовать x как MyProtocol, так и MySuperclass.

Только сегодня я решил очень похожую проблему в this thread, и я думал, что могу применить это здесь, но я не преуспеваю.

Идея заключалась бы в том, чтобы объявить тип переменной таким образом, чтобы она удовлетворяла ограничению <T where T:MySuperclass, T:MyProtocol>, но где я это помещаю? Все, что я пробовал до сих пор, на самом деле не имело смысла и не получилось.

Я пытался, например:

class Container<T where T:MySuperclass, T:MyProtocol> 

class Container {... var x:T ...} 

но экземпляр и назначить T в Container, и когда я делаю это я получаю ошибку компиляции:

class Container {... self.x = A() ....} 

«Тип A не является конвертируемой to 'T' "

Но на самом деле это должно быть потому, что A удовлетворяет ограничениям типа.

Редактировать: Спасибо arshajii's anwer Я понял, почему это невозможно. Но мне все еще нужно знать, как решить мою первоначальную проблему.

Я не знаю, действительно ли дженерики - правильный подход для этого. Я думаю, что мне не нужна переменная типа, мне нужно скорее нечто вроде совокупного типа ...

Редактировать 2- Я знаю, что могу реализовать это, просто выполнив подкласс. Было просто интересно, есть ли другие подходы. Но думать снова подкласс, кажется, лучший способ.

Заранее спасибо.

ответ

3

T может быть другой тип (например, FooImpl2) абсолютно не связан с FooImpl:

 
      Foo 
     / \ 
    FooImpl FooImpl2 

Foo экземпляра не может быть назначен (потенциальным) переменным типа FooImpl2, следовательно, ошибка.

+0

Спасибо! (+1) теперь я получаю эту часть. Но я до сих пор не знаю, как решить мою оригинальную проблему:/Может быть, я должен удалить тег Java, как решение того, что нужно специалисту Swift. – Ixx

0

Это всего лишь одна из стратегий для решения таких проблем.

// declare Protocol of MySuperClass type 
protocol MySuperClassType { 
    func mySuperClassMethod() 
} 

// Make the superclass conforms to it. 
class MySuperclass: MySuperClassType { 
//     ^^^^^^^^^^^^^^^^ 
    func mySuperClassMethod() {} 
} 

protocol MyProtocol { 
    func myProtocolMethod() 
} 

class A: MySuperclass, MyProtocol { 
    func myProtocolMethod() { } 
} 

class B: MySuperclass, MyProtocol { 
    func myProtocolMethod() { } 
} 

class Container { 

    // use "Protocol Composition" to declare the property. 
    var x: protocol<MySuperClassType, MyProtocol> 

    // ... 
} 
+0

Проблема с этим, в моем конкретном случае, заключается в том, что я хочу, чтобы переменная была пригодна для использования существующей apis как экземпляр MySuperClass. Пример: если MySuperClass является UIView, даже если я создаю расширение, чтобы x соответствовал протоколу «MySuperClassType» с помощью методов UIView, я не могу делать view.addSubview (x). – Ixx

+0

Затем вы должны взять еще одну стратегию, например: http://stackoverflow.com/questions/26474061/whats-the-swift-equivalent-of-declaring-typedef-someclasssomeprotocol-mytype/26475054#26475054 – rintaro

0
class Container {... var x: protocol<MySuperclassProtocol, MyProtocol> ....} 

Убедитесь, что MySuperclass соответствует MySuperclassProtocol

+0

Проблема с этим, в моем конкретном случае, заключается в том, что я хочу, чтобы переменная использовалась существующей apis как экземпляр MySuperClass. Пример: если MySuperClass является UIView, даже если я создаю расширение, чтобы x соответствовал протоколу «MySuperClassType» с помощью методов UIView, я не могу делать view.addSubview (x). – Ixx

+0

'view.addSubview (unsafeBitCast (x, UIView.self))' –

+0

Если бы я хотел бросить, я бы не стал задавать этот вопрос в первую очередь ... – Ixx

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