#initialization #swift #subclass #superclass
#инициализация #swift #подкласс #суперкласс
Вопрос:
У меня есть следующий класс с методом инициализации:
class user {
var name:String
var address:String
init(nm: String, ad: String) {
name = nm
address = ad
}
}
Я пытаюсь подклассировать этот класс, но я продолжаю получать ошибки в super.init()
части:
class registeredUser : user {
var numberPriorVisits: Int
// This is where things start to go wrong - as soon as I type 'init' it
// wants to autocomplete it for me with all of the superclass' arguments,
// and I'm not sure if those should go in there or not:
init(nm: String, ad: String) {
// And here I get errors:
super.init(nm: String, ad: String)
// etc....
В iBook от Apple есть примеры создания подклассов, но ни в одном из этих классов объектов нет init()
метода с какими-либо реальными аргументами в нем. Все их инициализации лишены аргументов.
Итак, как вы это делаете?
Комментарии:
1. Я думаю, вы можете (и должны) сделать свой код чище, объявив класс в верхнем регистре правильно?
Ответ №1:
В дополнение к ответу Чака, вам также необходимо инициализировать ваше новое введенное свойство перед вызовом super.init
Назначенный инициализатор должен гарантировать, что все свойства, введенные его классом, инициализированы, прежде чем он делегирует инициализатору суперкласса. (Язык программирования Swift -> Руководство по языку -> Инициализация)
Таким образом, чтобы заставить его работать:
init(nm: String, ad: String) {
numberPriorVisits = 0
super.init(nm: nm, ad: ad)
}
Эту простую инициализацию нулем можно было бы выполнить, также установив значение свойства по умолчанию равным нулю. Это также рекомендуется делать:
var numberPriorVisits: Int = 0
Если вам не нужно такое значение по умолчанию, имело бы смысл расширить ваш инициализатор, чтобы также установить новое значение для нового свойства:
init(name: String, ads: String, numberPriorVisits: Int) {
self.numberPriorVisits = numberPriorVisits
super.init(nm: name, ad: ads)
}
Комментарии:
1. Ну, я действительно надеялся, что не придется вводить значение по умолчанию 0 в
numberPriorVisits
— но вы говорите, что это действительно поощряется? Можете ли вы поделиться, где вы узнали, что это поощряется? Кроме того, в целом, я пытаюсь понять, какова наилучшая практика, когда дело доходит доinit's
в Swift. Лучше ли присвоить всем вашим свойствам значение по умолчанию и оставить метод инициализации без аргументов? Или лучше НЕ иметь значений по умолчанию и все это выполнять путем передачи аргументов вinit
?2. @sirab: Под поощрением я подразумеваю, что если вы хотите инициализировать его определенным значением, то рекомендуется использовать значение по умолчанию для свойства, а не устанавливать для свойства это значение внутри инициализатора. Что ж, если ваше решение работает со значениями по умолчанию, тогда нет необходимости в параметрах инициализатора.
3. @sirab: Я узнал, что это рекомендуется, прочитав руководство по языку. Та же глава, о которой я упоминал в своем ответе. В нем говорится: «Если свойство всегда принимает одно и то же начальное значение, укажите значение по умолчанию, а не устанавливайте значение в инициализаторе. Конечный результат тот же, но …» Иди и читай 🙂
4. хорошо, это имеет смысл — но только для свойств, которые действительно всегда принимают одно и то же начальное значение по умолчанию. Но я бы подумал, что имя пользователя или адрес не совсем соответствуют хорошему удобному значению по умолчанию — если только вы не хотите использовать пробел, как в: «». Но это кажется довольно грубым. Например, «ну, давайте просто сделаем это пустым, чтобы у нас по крайней мере было что -то, и поэтому мы могли избежать написания
init
метода — понимаете, что я имею в виду? Вопрос в том, считаете ли вы, что использование пробелов в качестве значений по умолчанию для строковых свойств является наилучшей практикой? (Я действительно пытаюсь найти здесь наилучший подход.)5. @sirab: Это абсолютно зависит от ваших потребностей. Итак, наилучшей практики нет. ИМХО, для вашего примера выглядит вполне очевидным установить имя и адрес внутри инициализатора в соответствии с параметрами и установить количество посещений по умолчанию равным 0 или 1, потому что пользователь новый.
Ответ №2:
В swift 2.0 и более поздних версиях это работает следующим образом (во всех случаях)
init(newString:String) {
super.init(string:newString)
// Designed initialiser
}
override init(someString: String) {
super.init(mainString: someString)
// Override initialiser when subclass some class
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
// Some boilerplate code to handle error (needed when override)
}
convenience init(newString:String, withParameters:Dictionary<String,String>) {
self.init(someString:newString)
//Convenience initialiser
}
Ответ №3:
Вы передаете аргументы инициализатору так же, как вы передаете аргументы обычному методу:
init(nm: String, ad: String) {
super.init(nm: nm, ad: ad)
}
Для справки, это показано в разделе «Назначенные и удобные инициализаторы в действии» руководства по языку Swift.
Ответ №4:
Вы пробовали устанавливать значение numberPriorVisits и изменять типы для вызовов на super
class user {
var name:String
var address:String
init(nm: String, ad: String) {
name = nm
address = ad
}
}
class registeredUser : user {
var numberPriorVisits: Int;
init(nm: String, ad: String) {
self.numberPriorVisits = 0;
super.init(nm: nm, ad: ad)
}
}