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。

更新於: 2023年4月11日

1K+ 閱讀量

開啟您的 職業生涯

透過完成課程獲得認證

立即開始
廣告