Зачем запрещать подклассам переопределять свойства суперкласса производным типом? - PullRequest
0 голосов
/ 25 августа 2018

Язык программирования Swift позволяет подклассам переопределять свойства суперкласса с тем же типом T, но не с другим типом S, даже когда S наследуется от T. Вот цитата из https://docs.swift.org/swift-book/LanguageGuide/Inheritance.html:

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

При переопределении методов Swift разрешает переопределенному методу подкласса возвращать тип, производный от возвращаемого типа метода суперкласса.

Мой вопрос таков: каков мотив запрета подклассам переопределять свойства суперкласса типом S, производным от T?

1 Ответ

0 голосов
/ 25 августа 2018

Это на самом деле не ограничивается Swift. Это сломало бы полиморфизм. См. Правила подтипов в википедии: Подтип

В основном рассмотрим следующий пример:

class A {
   var x: NSObject?
}

class B: A {
   override var x: NSNumber?
}

и рассмотрим:

let b = B(x: 1)
let a: A = b // it's a subclass, polymorphism allows to assign it to A
a.x = NSObject() // let's assign NSObject() because A.x takes NSObject
print(b.x) // b.x should be a NSNumber now but we have assigned a NSObject?

Вы должны понимать, что свойство представляет собой комбинацию двух функций: установщика и получателя. Вы можете добавить более конкретный тип (ковариантный тип) к получателю (возвращаемое значение функции), но вы не можете сделать это для установщика (параметры переопределяемой функции требуют контрастности).

Это также говорит о том, что это будет работать со свойством только для чтения:

class A {
    var x: NSObject? {
        return NSObject()
    }
}

class B: A {
    override var x: NSNumber? {
        return NSNumber()
    }
}
...