2015-03-18 5 views
1

Это моя структура наследованияOverride вар в соответствии с протоколом с вар в соответствии с ребенком переопределенном протокола вар

Протоколы

protocol BaseProtocol { 
} 

protocol ChildProtocol: BaseProtocol { 
} 

Классы

class BaseClass: NSObject { 

    var myVar: BaseProtocol! 
} 

class ChildClass: BaseClass { 

    override var myVar: ChildProtocol! 
} 

Я получаю ошибку компилятора:

Property 'myVar' with type 'ChildProtocol!' cannot override a property with type 'BaseProtocol!' 

Каков наилучший подход для достижения этого?

UPDATE

Я обновил этот вопрос, пытаясь реализовать решение с дженериков, но это не работает :(Это мой код (теперь настоящий, без примеров)

Протоколы

protocol TPLPileInteractorOutput { 
} 

protocol TPLAddInteractorOutput: TPLPileInteractorOutput { 

    func errorReceived(error: String) 
} 

Классы

class TPLPileInteractor<T: TPLPileInteractorOutput>: NSObject, TPLPileInteractorInput { 

    var output: T! 
} 

И мои дети

class TPLAddInteractor<T: TPLAddInteractorOutput>: TPLPileInteractor<TPLPileInteractorOutput>, TPLAddInteractorInput { 
} 

Ну, в моем TPLAddInteractor я не могу получить доступ к self.output, он выдает ошибку компиляции, например

'TPLPileInteractorOutput' does not have a member named 'errorReceived' 

Кроме того, когда я создаю экземпляр от TPLAddInteractor

let addInteractor: TPLAddInteractor<TPLAddInteractorOutput> = TPLAddInteractor() 

Я принимаю эту другую ошибку

Generic parameter 'T' cannot be bound to [email protected] protocol type 'TPLAddInteractorOutput' 

Любые мысли?

+0

[Это может быть полезным] (http://stackoverflow.com/questions/24094158/overriding-superclass-property-with-different-type-in-swift) и [Это] (Http: // StackOverflow.com/questions/26188903/swift-override-class-variables) –

+0

Спасибо @UmangBista, но принятое решение для меня не работает, компилятор говорит, что я не могу сделать нисходящий тип от другого типа. – emenegro

ответ

1

Я не думаю, что вы можете сделать это с protocols

так, как я бы решить эту проблему вы имеете это с использованием generics. Это означает, что у вас по существу есть такие классы (обновлено до рабочего примера).

Протоколы

protocol BaseProtocol { 
    func didSomething() 
} 
protocol ChildProtocol: BaseProtocol { 
    func didSomethingElse() 
} 

Классы

class BaseClass<T: BaseProtocol> { 
    var myProtocol: T? 

    func doCallBack() { 
     myProtocol?.didSomething() 
    } 
} 
class ChildClass<T: ChildProtocol> : BaseClass<T> { 
    override func doCallBack() { 
     super.doCallBack() 
     myProtocol?.didSomethingElse() 
    } 
} 

реализации/Пример использования

class DoesSomethingClass : ChildProtocol { 
    func doSomething() { 
     var s = ChildClass<DoesSomethingClass>() 
     s.myProtocol = self 
     s.doCallBack() 
    } 

    func didSomething() { 
     println("doSomething()") 
    } 
    func didSomethingElse() { 
     println("doSomethingElse()") 
    } 
} 

let foo = DoesSomethingClass() 
foo.doSomething() 

Реме mber, вам нужен класс, который фактически реализует протокол, и его класс THAT, который вы фактически определяете как общий тип для BaseClass/ChildClass. Поскольку код ожидает, что тип будет типом, который соответствует протоколу.

+0

Спасибо tskulbru, но это не совсем то же самое, мои ChildClass и BaseClass не соответствуют протоколу, которые являются переменными. – emenegro

+0

, используя мой ответ, не делает класс совместимым с протоколом, он заставляет класс содержать общий тип T, который имеет тип BaseProtocol или производные – tskulbru

+0

Еще раз спасибо, я пытаюсь его реализовать, я дам вам знать – emenegro

1

@tskulbru прав: это невозможно, и это не имеет ничего общего с вашими протоколами. Рассмотрим пример ниже, который также терпит неудачу ... На этот раз с Cannot override with a stored property 'myVar':

class Foo { 
} 

class Goo: Foo { 
} 

class BaseClass: NSObject { 
    var myVar: Foo! 
} 

class ChildClass: BaseClass { 
    override var myVar: Foo! 
} 

Чтобы понять, почему, давайте пересмотрит docs:

Overriding Properties

You can override an inherited instance or class property to provide your own custom getter and setter for that property, or to add property observers to enable the overriding property to observe when the underlying property value changes.

Подразумевается, что если вы собираетесь переопределить недвижимость, вы must написать собственный собственный геттер/сеттер, иначе вы must Добавить наблюдателей. Нельзя просто заменить один тип переменной другим.

Теперь для некоторых безудержных спекуляций: почему это так? Ну, подумайте, с одной стороны, что Swift рассчитан на для оптимизации скорости. Чтобы выполнить проверки типа времени выполнения, чтобы определить, действительно ли ваш var является Foo или Bar, это замедляет работу. Затем подумайте, что разработчики языка, вероятно, предпочитают композицию над наследованием. Если оба они верны, неудивительно, что вы не можете переопределить тип свойства.

Все, что сказано, если вам нужно получить эквивалентное поведение, решение @ tskulbru выглядит довольно элегантно, предполагая, что вы можете его скомпилировать. :)

+0

Спасибо clozach. Я взгляну на документы, потому что я начинаю изучать Swift и я не слишком много погрузились в дженерики больше, чем базис. – emenegro

0

Есть два способа, которыми вы можете пойти с кодом, в зависимости от того, что вы хотите достичь с помощью своего кода (вы не сказали нам).

Простой случай: вы просто хотите назначить объект, который подтверждает ChildProtocol для myVar. Решение: не переопределяйте myVar. Просто используйте его в ChildClass. Вы можете сделать это по дизайну языка Swift. Это одна из основ объектно-ориентированных языков.

Второй случай: вы не только хотите включить назначение экземпляров ChildProtocol, но также хотите отключить возможность назначать экземпляры BaseProtocol. Если вы хотите это сделать, используйте решение Generics, представленное здесь в разделе ответов.

Если вы не уверены, простой случай подходит именно вам.

Герд

+0

Привет, Герд. Я думал, что дело было ясным, я хочу переопределить var в базе с помощью другого var, соответствующего протоколу, который соответствует t o протокол var базы. Если я использую базовый класс, у меня есть одно поведение, если я использую его, у меня есть оба поведения, и я могу использовать его полиморфно с учетом базового класса. Я думаю, что это очень распространено и довольно просто. Я пытаюсь достичь решения generics. – emenegro

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