Swift 中使用不同型別覆蓋超類屬性
我們可以在 Swift 語言中定義一個從超類繼承的子類,這意味著可以使用 override 關鍵字覆蓋其屬性和方法。
但是,不能在子類中使用不同型別覆蓋屬性。預設情況下,子類必須覆蓋與超類型別相同的型別的屬性。
例如,假設您有一個 Person 類,其中 name 和 age 屬性的型別分別為 String 和 Double:
class Person { let name: String let age: Double init(name: String, age: Double) { self.name = name self.age = age } }
現在,假設您有一個名為 Student 的子類從 Person 繼承,並且您想將 age 屬性覆蓋為 Int 型別:
class Student: Person { let grade: Int override var age: Int { return age } }
此程式碼將產生編譯時錯誤,因為 Student 子類中 age 屬性的型別與 Person 超類中 age 屬性的型別不同。錯誤如下所示:
error: property 'age' with type 'Int' cannot override a property with type 'Double'
以下是一些在 Swift 中使用不同型別覆蓋超類屬性的示例:
示例 1:使用子型別覆蓋超類屬性
步驟 1 − 在此示例中,Dog 類使用相同的型別(String)覆蓋了 Animal 類的 name 屬性。
步驟 2 − 但是,它還添加了一個 didSet 觀察器,每當設定 name 屬性時列印“Dark!”。
步驟 3 − 這是一個關於如何在保持相同型別的同時向繼承屬性新增功能的示例。
import Foundation class Animal { var name: String init(name: String) { self.name = name } } class Dog: Animal { override var name: String { didSet { print("Bark!") } } } let dog = Dog(name: "Tommy") dog.name = "Harry"
輸出
Bark!
示例 2:使用計算屬性覆蓋超類屬性
import Foundation class Shape { var area: Double { fatalError("Subclasses must override this property") } } class Rectangle: Shape { var width: Double var height: Double init(width: Double, height: Double) { self.width = width self.height = height } override var area: Double { return width * height } } let rectangle = Rectangle(width: 10.0, height: 20.0) print(rectangle.area)
輸出
200.0
在此示例中,Shape 類定義了一個名為 area 的只讀屬性,如果它沒有被子類覆蓋,則會導致致命錯誤。Rectangle 類用一個計算屬性替換了矩形的 area 屬性,該屬性使用 width 和 height 值計算矩形的面積。這是一個說明如何使用計算屬性在每個子類中定義行為不同的繼承屬性的示例。
示例 3:在子類中使用額外變數覆蓋超類屬性
import Foundation class Person { let name: String let age: Double init(name: String, age: Double) { self.name = name self.age = age } } class Student: Person { var grade: Int init(grade: Int) { self.grade = grade super.init(name: "", age: 0.0) } } class School { var person = Person(name: "", age: 0.0) } class PrimarySchool: School { var student = Student(grade: 8) override var person: Person { get { return student } set { if let newStudent = newValue as? Student { student = newStudent } else { print("Incorrect student type for primary school.") } } } }
似乎不能使用 let 語法宣告一個屬性並在其子類中用 var 覆蓋它,反之亦然,這可能是因為超類實現可能不希望該屬性在初始化後發生更改。
因此,在這種情況下,也需要在超類中使用 'var' 宣告屬性以匹配子類(如上所示)。如果不能更改超類中的原始碼,那麼最好在每次需要修改人員時都銷燬當前的 RaceCar 並建立一個新的 PrimarySchool。
結論
Swift 提供了在子類中覆蓋屬性和方法的靈活性。此外,您可以在子類中使用不同型別覆蓋超類的屬性。
為此,如果要更改超類屬性的實際型別,可以使用計算屬性而不是儲存屬性。使用計算屬性,您可以使用不同的型別覆蓋 getter 和 setter。