Почему второй инициализатор в базовом классе нарушает компиляцию? - PullRequest
1 голос
/ 16 мая 2019

При наличии базового класса, производного класса и расширения с удобным инициализатором компилятор выдает ошибку, если в базовый класс добавлен второй инициализатор, как показано ниже: sscce

#!/usr/bin/env swift 
class A {
    required init(a : Int){}
    init(b: Int){} // when removing this initializer everything works fine
}

class B: A {
    required init(a : Int){ super.init(a: a) }
}

extension A {
    convenience init(c : Int) { self.init(a: c) }
}

let b: B = B(c: 1)

С двумя инициализаторами в базовом классе выдается следующая ошибка:

... error: incorrect argument label in call (have 'c:', expected 'a:')
let b: B = B(c: 1)
            ^~
             a

Помимо сообщения об ошибке, которое не очень полезно в этом случае, я не совсем уверен, является ли это ожидаемым поведением или ошибкой в ​​swift.

Информация о версии Swift:

Apple Swift version 5.0.1 (swiftlang-1001.0.82.4 clang-1001.0.46.5)
Target: x86_64-apple-darwin18.5.0

1 Ответ

1 голос
/ 16 мая 2019

С Автоматическое наследование инициализатора :

При условии, что вы предоставляете значения по умолчанию для любых новых свойств, вводимых в подкласс, применяются следующие два правила:

Правило 1
Если ваш подкласс не определяет никаких назначенных инициализаторов, он автоматически наследует все свои инициализаторы, назначенные суперклассом.

Правило 2
Если ваш подкласс обеспечивает реализацию всех его назначенных суперклассовинициализаторы - либо наследуя их согласно правилу 1, либо предоставляя пользовательскую реализацию как часть его определения, - затем автоматически наследуют все удобные инициализаторы суперкласса.

Без init(b:) в class A, class B автоматически наследует init(c:) от расширения и все работает.

Но когда вы добавляете init(b:) к class A, class B больше не следует ни одному из правил, и поэтому class B нетбольше автоматически наследует init(c:) от расширения.Это приводит к ошибке, поскольку class B теперь имеет только один инициализатор init(a:) и никаких других.

Вы можете решить проблему, переопределив init(b:) в class B.После этого class B снова автоматически получает init(c:) от расширения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...