Я бачив багато причин, чому проектування API з використанням змінних замість функцій є проблематичним, і для мене використання обчислюваних властивостей відчуває себе як вирішення. Є вагомі причини, щоб ваші змінні екземпляри були інкапсульовані. Тут я створив протокол Automobile, якому відповідає Автомобіль. Цей протокол має метод accessor, який повертає об'єкт Chassis. Оскільки автомобіль відповідає йому, підклас RaceCar може змінити його і повернути інший підклас Шасі. Це дозволяє класу Car програмувати інтерфейс (Automobile), а клас RaceCar, який знає про RacingChassis, може отримати доступ до змінної _racingChassis безпосередньо.
class Chassis {}
class RacingChassis: Chassis {}
protocol Automobile {
func chassis() -> Chassis
}
class Car: Automobile {
private var _chassis: Chassis
init () {
_chassis = Chassis()
}
func chassis() -> Chassis {
return _chassis
}
}
class RaceCar: Car {
private var _racingChassis: RacingChassis
override init () {
_racingChassis = RacingChassis()
super.init()
}
override func chassis() -> Chassis {
return _racingChassis
}
}
Інший приклад того, чому розробляється API з використанням змінних, - це коли у протоколі є змінні. Якщо ви хочете розбити всі функції протоколу на розширення, ви можете, за винятком збережених властивостей, не можна розміщувати в розширеннях і їх потрібно визначати в класі (для компіляції цього коду вам доведеться коментувати код у Клас AdaptableViewController та видаліть змінну режиму з розширення):
protocol Adaptable {
var mode: Int { get set }
func adapt()
}
class AdaptableViewController: UIViewController {
// var mode = 0
}
extension AdaptableViewController: Adaptable {
var mode = 0 // compiler error
func adapt() {
//TODO: add adapt code
}
}
У наведеному вище коді буде помилка компілятора: "Розширення можуть не мати збережених властивостей". Ось як можна переписати приклад вище, щоб все в протоколі можна було відокремити в розширенні, використовуючи замість нього функції:
protocol Adaptable {
func mode() -> Int
func adapt()
}
class AdaptableViewController: UIViewController {
}
extension AdaptableViewController: Adaptable {
func mode() -> Int {
return 0
}
func adapt() {
// adapt code
}
}
strong
властивістю, і я отримував помилку, намагаючись його замінити - але, здається, я пропустив, що це перекладається на "неявно розпакований факультативний" (chassis!
) у Швидко, такoverride var chassis : Chassis!
це виправляєш.