Ответ 1
Последняя строка в вашем примере кода больше не дает ошибку компиляции (начиная с Swift 3). Об этом не говорится в Swift 3 Language Changes, поэтому я могу только предположить, что это была ошибка.
У меня есть следующие коды:
class ILProperty<T> {
var value: T?
init(_ value: T) {
self.value = value
}
}
typealias ILStringProperty = ilStringProperty<String>
class ilStringProperty<String>: ILProperty<String> {
}
let x = ILStringProperty("X")
Последняя строка - это ошибка компиляции:
'ILStringProperty' не может быть сконструирован, потому что у него нет доступных инициализаторов
Если я переопределяю init:
override init(_ value: String) {
super.init(value)
}
будет работать, но мне это не нравится. Почему мне нужно переопределять его, когда я не буду добавлять/изменять его?
Я что-то делаю неправильно?
Обновление: последующие вопросы к ответам Никиты Леонова и Икаро
Прежде всего, для всех свойств должно быть значение по умолчанию, я думаю, что я удовлетворил это правило, когда опциональный var по умолчанию имеет значение nil, не так ли? Хотя даже если я пишу var value: T? = nil
, это не решает.
Затем из той же documentation раздела "Автоматическое наследование инициализатора":
инициализаторы суперкласса автоматически наследуются, если выполняются определенные условия
Одно из условий:
Если ваш подкласс не определяет какие-либо назначенные инициализаторы, он автоматически наследует все его инициализаторы, назначенные суперклассам.
Где я действительно думаю, что приведенный выше код действительно соответствует. Это действительно будет работать, если я не буду использовать generics:
class ILProperty {
var value: Any?
init(_ value: Any) {
self.value = value
}
}
class ILStringProperty: ILProperty {
}
let x = ILStringProperty("X")
Должно ли это правило также применяться к родовым классам?
Последняя строка в вашем примере кода больше не дает ошибку компиляции (начиная с Swift 3). Об этом не говорится в Swift 3 Language Changes, поэтому я могу только предположить, что это была ошибка.
Swift предоставляет инициализатор по умолчанию для любой структуры или базового класса который предоставляет значения по умолчанию для всех своих свойств и не по крайней мере, один инициализатор. Инициализатор по умолчанию просто создает новый экземпляр со всеми его свойствами, установленными для их значения по умолчанию.
Ваш класс ilStringProperty не является базовым классом, поскольку он наследует от ILProperty, поэтому он должен иметь инициализатор, если вы создаете одно или переопределяете одно, не имеет значения, поскольку у вас есть хотя бы один инициализатор в вашем классе, поскольку swift не даст его для свободный.
Как ganzogo упоминается, что он работает отлично с последним Swift (3.0). Кроме того, почему вы объявляете отдельный класс для назначения typealias
? Я пробовал это на игровой площадке, и все выглядит нормально:
class ILProperty<T> {
var value: T?
init(_ value: T) {
self.value = value
}
}
typealias ILStringProperty = ILProperty<String>
let x = ILStringProperty("X")
Вот еще одна цитата из документации Apple
В отличие от подклассов в Objective-C подклассы Swift не наследуют их инициализаторы суперкласса по умолчанию. Подход Swifts предотвращает ситуация, в которой наследуется простой инициализатор из суперкласса более специализированным подклассом и используется для создания нового экземпляра подкласс, который не полностью или правильно инициализирован.
В Документ Swift Programming Language из apple смотрите раздел "Наследование и переопределение инициализатора".
Я понимаю ваше разочарование, но быстрый способ справиться с инициализатором концептуально лучше.