2015-08-21 3 views
9

Так что я думал о пользовательском шаблоне в своем проекте, но я не могу заставить его работать. Основная идея состоит в том, чтобы изменить typealias на каждый подкласс, чтобы получить доступ к конкретному интерфейсу подкласса.Swift: переопределение типов внутри подкласса

protocol InstanceInterface: class { 

    typealias Interface 

    var interface: Interface { get } 
} 

// Baseclass 
protocol FirstClassInterface: class { /* nothing here for the example */ } 

class FirstClass: InstanceInterface, FirstClassInterface { 

    typealias Interface = FirstClassInterface 

    var interface: Interface { return self } 
} 

// Subclass 
protocol SecondClassInterface: FirstClassInterface { 

    func foo() 
} 

class SecondClass: FirstClass, SecondClassInterface { 

    typealias Interface = SecondClassInterface // <--- This does nothing :(

    func foo() { print("hello world") } // Swift 2.0 here 
} 

// Lets say I want to call foo trough the interface 
let test = SecondClass() 

test.interface.foo() // 'Interface' does not have a member named 'foo' 

Есть ли что-то, что я делаю неправильно или я неправильно понимаю некоторые понятия Swift здесь ?! Мне нужно подклассы здесь, чтобы не реализовывать все из суперклассических протоколов снова и снова. Возможна ли моя маленькая модель? Буду признателен за любую помощь. :)

ответ

6

К сожалению, для этой проблемы не существует обходного пути.

Основная идея переопределить typealias будет работать в этом случае, но необходимо учитывать следующее:

protocol TakeAndGet { 
    typealias T 
    func take(value: T) 
    func get() -> T 
} 

class FirstClass: TakeAndGet { 
    typealias T = FirstClass 

    var property = 0 

    func take(value: T) { 
     value.property = 4 
    } 

    func get() -> T { 
     return FirstClass() 
    } 
} 

class SecondClass: FirstClass { 

    typealias T = SecondClass 

    var property2 = "hello" 
} 

Если typealias из SecondClass перекрывает другой метод take будет работать, поскольку он занимает подкласс, который может рассматриваться как суперкласс. Но метод get не может неявно конвертировать FirstClass в SecondClass. Поэтому невозможно переопределить typealias.

Теперь, если мы хотим переопределить функцию get с get() -> SecondClass, она не будет работать, поскольку она не имеет той же самой подписи, что и в суперклассе. Кроме того, мы унаследуем get метод, который приводит к неоднозначному использованию:

SecondClass().get() // which type gets returned? SecondClass or FirstClass 

Таким образом, вы должны попробовать другой подход.

+1

Я вижу момент сейчас. Но все-таки должна быть какая-то ошибка или предупреждение, если вы переопределите типы сообщений внутри подкласса !? Я имею в виду, что он ничего не делает, даже для вашего примера он все равно будет придерживаться FirstClass внутри SecondClass, или я снова ошибаюсь? В чем смысл переопределения типов? – DevAndArtist

+1

@DevAndArtist Дело в том, что 'typealias' нельзя переопределить, и если вы объявляете новый с тем же именем, что и в' SecondClass', он затеняет другой. Это означает, что 'T' входит в область« SecondClass »другого типа, но не меняет' T' 'FirstClass'. – Qbyte

5

Будет что-то вроде этой работы для ваших целей?

class MyClass<T> { 

} 

class MySubclass1: MyClass<String> { 

} 

class MySubclass2: MyClass<Int> { 

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