Widziałem wiele powodów, dla których projektowanie API przy użyciu zmiennych zamiast funkcji jest problematyczne, a używanie obliczonych właściwości wydaje mi się obejściem. Istnieją dobre powody, aby zachować hermetyzację zmiennych instancji. Tutaj stworzyłem protokół Samochód, z którym jest zgodny samochód. Ten protokół ma metodę akcesora, która zwraca obiekt Chassis. Ponieważ Car jest z nim zgodny, podklasa RaceCar może go zastąpić i zwrócić inną podklasę Chassis. Pozwala to klasie Car na programowanie w interfejsie (Automobile), a klasie RaceCar, która wie o RacingChassis, może uzyskać bezpośredni dostęp do zmiennej _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
}
}
Innym przykładem załamania się projektowania interfejsu API przy użyciu zmiennych jest sytuacja, gdy w protokole są zmienne. Jeśli chcesz rozbić wszystkie funkcje protokołu na rozszerzenia, które możesz, z wyjątkiem tego, że przechowywane właściwości nie mogą być umieszczane w rozszerzeniach i muszą być zdefiniowane w klasie (aby to skompilować, musisz odkomentować kod w AdaptableViewController i usuń zmienną trybu z rozszerzenia):
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
}
}
Powyższy kod będzie miał następujący błąd kompilatora: „Rozszerzenia mogą nie mieć zapisanych właściwości”. Oto, jak możesz ponownie napisać powyższy przykład, aby wszystko w protokole można było oddzielić w rozszerzeniu za pomocą zamiast tego funkcji:
protocol Adaptable {
func mode() -> Int
func adapt()
}
class AdaptableViewController: UIViewController {
}
extension AdaptableViewController: Adaptable {
func mode() -> Int {
return 0
}
func adapt() {
// adapt code
}
}
strongwłaściwością i otrzymywałem błąd podczas próby jej przesłonięcia - ale wygląda na to, że przeoczyłem, że przekłada się to na „niejawnie rozpakowany opcjonalny” (chassis!) w Szybki, więcoverride var chassis : Chassis!naprawia to.