2017-02-22 106 views
2

Я пытаюсь понять, почему Swift применяет класс, соответствующий протоколу с инициализатором, который должен быть помечен как требуется. Это, по существу, принуждает любые подклассы также реализовать этот инициализатор. Разумеется, назначенный инициализатор суперкласса был бы унаследован?Swift: реализация инициализатора протокола в классе

Котировки ниже, взяты из Руководства Swift Язык: https://developer.apple.com/library/prerelease/content/documentation/Swift/Conceptual/Swift_Programming_Language/Protocols.html#//apple_ref/doc/uid/TP40014097-CH25-ID272

Вы можете реализовать требование протокола инициализации на соответствующей класса либо как назначенный инициализаторе или удобства инициализаторе. В обоих случаях необходимо отметить реализацию инициализатора с требуемого модификатора:

class SomeClass: SomeProtocol { 
    required init(someParameter: Int) { 
     // initializer implementation goes here 
    } 
} 

class SomeSubclass: SomeClass { 
    required init(someParameter: Int) { // enforced to implement init again 
     // initializer implementation goes here 
    } 
} 

Использование требуемого модификатора гарантирует, что вы предоставляете явно или унаследованное выполнение требований инициализатора на всех подклассов соответствующего класса, так что они также соответствуют протоколу .

EDIT: я первоначально не упомянул, что я в настоящее время ограничивается Swift 2.1. Это, похоже, проблема компилятора в этой версии и не встречается в более поздних версиях.

ответ

3

Конечно назначенный суперкласс инициализатор будет наследоваться?

Нет, не всегда. Если подкласс определяет свои собственные назначенные инициализаторы, то он не будет автоматически наследовать назначенные инициализаторы суперкласса. Рассмотрим следующий пример:

class Foo { 
    init() {} 
} 

class Bar : Foo { 

    var str: String 

    init(str: String) { 
     self.str = str 
    } 
} 

let b = Bar() // illegal – what value would the 'str' property have? 

Как Bar определяет свой собственный init(str:) назначенный Инициализатора, он автоматически не наследует Foo «S назначенных инициализатора init(). Это предотвращает небезопасную инициализацию в случаях, когда подкласс объявляет собственные хранимые свойства.

Маркировка init() в requiredнавязываетBar имеет init(), будь то путем предоставления своей собственной реализации:

class Foo { 
    required init() {} 
} 

class Bar : Foo { 

    var str: String 

    init(str: String) { 
     self.str = str 
    } 

    // implement required init(), as Bar defines its own designated initialiser. 
    required init() { 
     self.str = "foo" // now str is correctly initialised when calling init() 
    } 
} 

let b = Bar() // now legal 

Или наследованием реализации Foo «s (когда Bar не определяет свои собственные назначенные инициализаторов) :

class Foo { 
    required init() {} 
} 

class Bar : Foo { 
    // inherits init() from Foo, as Bar doesn't define its own designed initialisers. 
} 

let b = Bar() // legal 
+0

Это имеет смысл для аргументации пометить его по мере необходимости. Я предполагаю, что отбросил меня в том, что в Swift 2.1 компилятор принуждает вас реализовать инициализатор суперклассов, даже если подкласс не имеет назначенных инициализаторов. –

+0

Отметить это как принятое, поскольку он объясняет мой вопрос: «Конечно, назначенный инициализатор суперкласса был бы унаследован?». Первоначальная проблема, которую я имел, была связана с ограничением Swift 2.1. –

2

Вы не являетесь силой для реализации инициализатора в подклассе. Рассмотрим следующий пример, который компилирует просто отлично:

protocol SomeProtocol { 
    init(someParameter: Int) 
} 


class SomeClass: SomeProtocol { 
    required init(someParameter: Int) { 
     // initializer implementation goes here 
     print(someParameter) 
    } 
} 


class SomeSubclass: SomeClass { 
    // Notice that no inits are implemented here 
} 

_ = SomeClass(someParameter: 123) 
_ = SomeSubclass(someParameter: 456) 
+0

Я должен был упомянуть, что в настоящее время я ограничен Swift 2.1, поэтому ку ld будет ошибкой в ​​этом выпуске. С какой версией вы скомпилировались? –

+0

Swift 3. Swift 2 устарел. – Alexander

+0

Спасибо за проверку версии.Я понимаю, что он устарел, но в настоящее время я ограничен его использованием из-за не зависящих от меня обстоятельств. Хорошо знать, что это было рассмотрено в более поздних версиях. –