2017-01-22 4 views
1

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

init(values: [String: Any]) { 
    updateValues(dict: values) 
} 

и

func updateValues(dict: [String: Any]){ 
    //To be implemented in subclasses 
} 

Переопределелив updateValues() в подклассах, и за счет использования динамической диспетчеризации, чтобы гарантировать, что каждый подкласс правильно устанавливает свои собственные переменные, все, кажется, работает.

Например, в классе пользователя, свойства объявляются так:

var name: String? 
var uid: String? 
var email: String? 
var username: String? 

и его updateValues() выглядит следующим образом:

override func updateValues(dict: [String: Any]) { 
    self.name = dict["name"] as? String 
    self.uid = dict["uid"] as? String 
    self.email = dict["email"] as? String 
    self.username = dict["username"] as? String 
} 

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

init(name: String?, uid: String?, email: String?, username: String?){... 

Однако это инициализатор декларация создает нежелательный результат. В соответствии с правилами Swift «Автоматическое наследование инициализатора» на странице this, как только один назначенный инициализатор предоставляется подклассу, он больше не наследует инициализаторы суперкласса. Это делает наследование довольно утомительным, так как теперь я должен переопределить инициализатор, который я хочу автоматически наследовать, и просто вызвать super.init() для каждого подкласса. Я также должен переписать комментарии для каждого примера этого обходного пути override init - super.init().

Есть ли все равно, чтобы по-прежнему наследовать назначенные суперкласса инициализаторы? Или я думаю об этом неправильно?

Примечание. Я прокомментировал назначенные инициализаторы подкласса, и инициализаторы суперкласса были автоматически унаследованы. Фактически нет изменений в функциональности, добавляя дополнительные инициализаторы подкласса (или раскомментируя их), поэтому я хотел бы найти способ обойти проверку безопасности Swift.

ответ

1

Вы должны (и должны) всегда вызывать назначенный инициализатор. Это значит, что это назначенный инициализатор. Если ваш назначенный инициализатор равен init(value:), то init(name: String?, uid: String?, email: String?, username: String?) должен быть инициализатором удобства, который его вызывает. Реализация нового «обязательного вызова» (т. Е. Назначенного инициализатора) означает, что назначенный инициализатор суперкласса является недопустимым для этого подкласса, но здесь это не так. Поэтому просто напишите:

convenience init(name: String?, uid: String?, email: String?, username: String?) { 
    self.init(values: ["name": name, "uid": uid, "email": email, "username": username]) 
} 

Это не должно приводить к аннулированию ваших других позиций.

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