Реализация NSCopying в Swift с подклассами
рассмотрим два занятия. Первый -Vehicle, an NSObject подкласс, который соответствует NSCopying:
class Vehicle : NSObject, NSCopying {
var wheels = 4
func copyWithZone(zone: NSZone) -> AnyObject {
let vehicle = self.dynamicType()
vehicle.wheels = self.wheels
return vehicle
}
}
второй класс Starship, наследует от Vehicle:
class Starship : Vehicle {
var photonTorpedos = 6
var antiGravity = true
override func copyWithZone(zone: NSZone) -> AnyObject {
let starship = super.copyWithZone(zone) as Starship
starship.photonTorpedos = self.photonTorpedos
starship.antiGravity = self.antiGravity
return starship
}
}
этот код не компилируется, потому что:
построение объекта типа класса "транспортное средство" со значением метатипа должно использовать инициализатор "required".
поэтому я продолжаю и добавляю необходимый инициализатор:
required override init () {
super.init()
}
и теперь приложение компилируется, и Starship объекты отвечают на copy() правильно.
два вопроса:
- почему для построения объекта с метатипом требуется
requiredинициализатор? (Похоже, инициализатор, который я написал, ничего не делает.) - есть ли что-нибудь, что я написал неправильно, или должны добавить в инициализатор? Есть дело, которое я не рассматриваю?
2 ответов
Короткий Ответ:
вы не можете использовать self.dynamicType() без маркировки init() as required потому что нет никаких гарантий подклассов Vehicle также будет осуществлять init().
Изучение Проблемы
посмотреть Язык Программирования Swift: Инициализация, упоминается как
подклассы не наследуют свои инициализаторы суперклассов по умолчанию
ситуации, в которых подкласс будет наследовать initialisers его суперкласса являются:
предполагая, что вы предоставляете значения по умолчанию для любых новых свойств введите в подкласс следующие два правила:
Правило 1
если ваш подкласс не определяет никаких назначенных инициализаторов, это автоматически наследует весь назначенный суперкласс инициализаторы.
Правило 2
если ваш подкласс предоставляет реализацию всего своего суперкласса назначенные инициализаторы-либо путем наследования их в соответствии с правилом 1, либо предоставление пользовательской реализации как части ее определения-тогда это автоматически наследует все инициализаторы удобства суперкласса.
рассмотрим пример:
class MySuperclass {
let num = 0
// MySuperclass is given `init()` as its default initialiser
// because I gave `num` a default value.
}
class MySubclass : MySuperclass {
let otherNum: Int
init(otherNum: Int) {
self.otherNum = otherNum
}
}
согласно информации выше, так как MySubclass определено свойство otherNum без начального значения он не наследует автоматически init() С MySuperclass.
теперь предположим, что я хочу добавить следующий метод в MySuperclass:
func myMethod() {
println(self.dynamicType().num)
}
вы получите ошибку, которую вы описали, потому что нет никаких гарантий подклассов MySuperclass реализовать init() (и в этом примере они этого не делают).
чтобы решить эту проблему, вам необходимо отметить init() as required, для обеспечения всех подклассов MySuperclass реализовать init(), и поэтому вызов self.dynamicType() это действительная вещь. Это та же проблема, что и в вашем вопросе: Swift знает Vehicle осуществляет init(), однако он не знает, что все подклассы реализуют init() и так вам нужно сделать это required.
альтернативным решением, которое не подходит в вашем примере, является пометка Vehicle as final, что означает Vehicle не может быть разделен на подклассы. Тогда вы сможете использовать self.dynamicType(); но вы также можете просто использовать Vehicle() in это дело.
вам понадобится required инициализатор, потому что для реализации подкласса требуется инициализатор в Swift.
в документации Swift на требуются nitializers:
вы также должны написать необходимый модификатор перед каждым подклассом реализация необходимого инициализатора, чтобы указать, что требование инициализатора применяется к дальнейшим подклассам в цепочке.