Tôi đã thấy rất nhiều lý do tại sao việc thiết kế API bằng các biến thay vì các hàm là vấn đề và đối với tôi, việc sử dụng các thuộc tính được tính toán có cảm giác như một cách giải quyết. Có những lý do chính đáng để giữ các biến thể hiện của bạn được gói gọn. Ở đây tôi đã tạo ra một giao thức Ô tô mà Xe tuân thủ. Giao thức này có một phương thức truy cập trả về một đối tượng Khung. Vì Xe tuân theo nó, lớp con RaceCar có thể ghi đè lên nó và trả về một lớp con Khung gầm khác. Điều này cho phép lớp Xe hơi lập trình thành giao diện (Ô tô) và lớp RaceCar biết về RacingChrame có thể truy cập trực tiếp vào biến _racingChrame.
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
}
}
Một ví dụ khác về lý do tại sao thiết kế API sử dụng các biến bị hỏng là khi bạn có các biến trong giao thức. Nếu bạn muốn tách tất cả các chức năng giao thức thành một phần mở rộng bạn có thể, ngoại trừ các thuộc tính được lưu trữ không thể được đặt trong các phần mở rộng và phải được xác định trong lớp (để có được điều này để biên dịch, bạn phải bỏ mã trong Lớp AdaptableViewControll và loại bỏ biến chế độ khỏi phần mở rộng):
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
}
}
Đoạn mã trên sẽ có lỗi trình biên dịch này: "Phần mở rộng có thể không có thuộc tính được lưu trữ". Dưới đây là cách bạn có thể viết lại ví dụ trên để mọi thứ trong giao thức có thể được tách ra trong phần mở rộng bằng cách sử dụng các hàm thay thế:
protocol Adaptable {
func mode() -> Int
func adapt()
}
class AdaptableViewController: UIViewController {
}
extension AdaptableViewController: Adaptable {
func mode() -> Int {
return 0
}
func adapt() {
// adapt code
}
}
strong
tính và tôi đã gặp lỗi khi ghi đè lên nó - nhưng có vẻ như tôi đã bỏ lỡ rằng nó chuyển thành "tùy chọn không được bao bọc" (chassis!
) Swift, vì vậyoverride var chassis : Chassis!
sửa nó.