ฉันได้เห็นเหตุผลมากมายว่าทำไมการออกแบบ API โดยใช้ตัวแปรแทนฟังก์ชันจึงเป็นปัญหาและสำหรับฉันที่ใช้คุณสมบัติที่คำนวณแล้วรู้สึกเหมือนเป็นวิธีแก้ปัญหา มีเหตุผลที่ดีที่จะเก็บตัวแปรอินสแตนซ์ของคุณไว้ ที่นี่ฉันได้สร้างโปรโตคอลรถยนต์ที่สอดคล้องกับรถยนต์ โปรโตคอลนี้มีวิธีการเข้าถึงที่ส่งคืนอ็อบเจ็กต์ Chassis เนื่องจากรถเป็นไปตามนั้นคลาสย่อย RaceCar จึงสามารถแทนที่และส่งคืนคลาสย่อยแชสซีอื่นได้ สิ่งนี้ทำให้คลาส Car สามารถตั้งโปรแกรมไปยังอินเทอร์เฟซ (รถยนต์) และคลาส 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!
แก้ไข