Swift繼承

取而不是定義更多形式的能力被定義為繼承。 通常,類可以從另一個類繼承方法,屬性和功能。 類可以進一步分類為子類和超類。

  • 子類 - 當一個類繼承另一個類的屬性,方法和功能被稱為子類別。
  • 超類 - 包含從其自身繼承其他類的屬性,方法和函數的類稱為超類。

Swift 4類包含超類,它調用和訪問方法,屬性,函數和重寫方法。 此外,屬性觀察器還用於添加屬性並修改存儲或計算的屬性方法。

基類

不從其他類繼承方法,屬性或函數的類稱為“基類”。

class StudDetails {
   var stname: String!
   var mark1: Int!
   var mark2: Int!
   var mark3: Int!

   init(stname: String, mark1: Int, mark2: Int, mark3: Int) {
      self.stname = stname
      self.mark1 = mark1
      self.mark2 = mark2
      self.mark3 = mark3
   }
}

let stname = "Swift 4"
let mark1 = 98
let mark2 = 89
let mark3 = 76

print(stname)
print(mark1)
print(mark2)
print(mark3)

當使用playground運行上述程式時,得到以下結果 -

Swift 4
98
89
76

StudDetails類在此定義為基類,用於包含學生姓名,三個科目分數為:mark1mark2mark3let關鍵字用於初始化基類的值,基類的值使用print方法顯示在playground中。

子類

將新類基於現有類的行為定義為“子類”。 子類繼承其基類的屬性,方法和函數。 在基類名稱之前使用符號:: 來定義子類 -

class StudDetails {
   var mark1: Int;
   var mark2: Int;

   init(stm1:Int, results stm2:Int) {
      mark1 = stm1;
      mark2 = stm2;
   }
   func print() {
      print("Mark1:\(mark1), Mark2:\(mark2)")
   }
}

class display : StudDetails {
   init() {
      super.init(stm1: 93, results: 89)
   }
}

let marksobtained = display()
marksobtained.print()

當使用playground運行上述程式時,得到以下結果 -

Mark1:93, Mark2:89

StudDetails被定義為超類中,超類中聲明學生分數。子類display用於從超類繼承分數。 子類定義學生分數並調用print()方法來顯示學生分數。

覆蓋

訪問超類實例,類型方法,實例,類型屬性和下標子類提供了覆蓋的概念。override關鍵字用於覆蓋超類中聲明的方法。

訪問超類方法,屬性和下標
super關鍵字用作訪問超類中聲明的方法,屬性和下標的首碼。

覆蓋 訪問方法,屬性和下標
方法 super.somemethod()
屬性 super.someProperty()
下標 super[someIndex]

方法覆蓋

繼承的實例和類型方法可以被override關鍵字覆蓋子類中定義的方法。 這裏在子類中覆蓋print()以訪問超類print()中的type屬性。 另外,cricket()超類的新實例創建為cricinstance

class cricket {
   func print() {
      print("Welcome to Swift 4 Super Class")
   }
}

class tennis: cricket {
   override func print() {
      print("Welcome to Swift 4 Sub Class")
   }
}

let cricinstance = cricket()
cricinstance.print()

let tennisinstance = tennis()
tennisinstance.print()

當使用playground運行上述程式時,得到以下結果 -

Welcome to Swift Super Class
Welcome to Swift Sub Class

屬性覆蓋

可以覆蓋繼承的實例或類屬性,以便為該屬性提供自己的自定義gettersetter,或者添加屬性觀察器以使覆蓋屬性能夠在基礎屬性值更改時進行觀察。

覆蓋屬性getter和setter
Swift 4允許用戶提供自定義getter和setter來覆蓋繼承的屬性,無論它是存儲屬性還是計算屬性。 子類不知道繼承的屬性名稱和類型。 因此,需要在子類中指定超類中指定的覆蓋屬性的名稱和類型。

可以通過兩種方式完成 -

  • 當為覆蓋屬性定義setter時,也必須定義getter
  • 當不想修改繼承的屬性getter時,可以簡單地將繼承的值通過語法super.someProperty傳遞給超類。

示例代碼

class Circle {
   var radius = 12.5
   var area: String {
      return "of rectangle for \(radius) "
   }
}

class Rectangle: Circle {
   var print = 7
   override var area: String {
      return super.area + " is now overridden as \(print)"
   }
}

let rect = Rectangle()
rect.radius = 25.0
rect.print = 3
print("Radius \(rect.area)")

當使用playground運行上述程式時,得到以下結果 -

Radius of rectangle for 25.0  is now overridden as 3

覆蓋屬性觀察員

當需要為繼承的屬性添加新屬性時,在Swift 4中引入了“屬性覆蓋”概念。它會在更改繼承的屬性值時通知用戶。 但是覆蓋不適用於繼承的常量存儲屬性和繼承的只讀計算屬性。

class Circle {
   var radius = 12.5
   var area: String {
     return "of rectangle for \(radius) "
   }
}

class Rectangle: Circle {
   var print = 7
   override var area: String {
      return super.area + " is now overridden as \(print)"
   }
}

let rect = Rectangle()
rect.radius = 25.0
rect.print = 3
print("Radius \(rect.area)")

class Square: Rectangle {
   override var radius: Double {
      didSet {
         print = Int(radius/5.0)+1
      }
   }
}

let sq = Square()
sq.radius = 100.0
print("Radius \(sq.area)")

當使用playground運行上述程式時,得到以下結果 -

Radius of rectangle for 25.0  is now overridden as 3
Radius of rectangle for 100.0  is now overridden as 21

防止覆蓋的final屬性

當不需要其他人訪問超類方法,屬性或下標時,Swift 4引入’final’屬性以防止覆蓋。 當final屬性聲明後,下標將不允許覆蓋超類方法,屬性及其下標。但不要求一定在“超類”中擁有final屬性。 當類聲明為final時,限制創建基於此類的子類。

final class Circle {
   final var radius = 12.5
   var area: String {
      return "of rectangle for \(radius) "
   }
}

class Rectangle: Circle {
   var print = 7
   override var area: String {
      return super.area + " is now overridden as \(print)"
   }
}

let rect = Rectangle()
rect.radius = 25.0
rect.print = 3
print("Radius \(rect.area)")

class Square: Rectangle {
   override var radius: Double {
      didSet {
         print = Int(radius/5.0)+1
      }
   }
}

let sq = Square()
sq.radius = 100.0
print("Radius \(sq.area)")

當使用playground運行上述程式時,得到以下結果 -

<stdin>:14:18: error: var overrides a 'final' var
override var area: String {
^
<stdin>:7:9: note: overridden declaration is here
var area: String {
^
<stdin>:12:11: error: inheritance from a final class 'Circle'
class Rectangle: Circle {
^
<stdin>:25:14: error: var overrides a 'final' var
override var radius: Double {
^
<stdin>:6:14: note: overridden declaration is here
final var radius = 12.5

由於超類被聲明為final並且其數據類型也被聲明為final,因此程式將不允許創建子類,並且拋出錯誤。


上一篇: Swift下標 下一篇: Swift構造函數(Initializer)