当前位置: 首页 > 教程 > Swift >

Swift继承

精华
小牛编辑
128浏览
2023-03-14

取而不是定义更多形式的能力被定义为继承。 通常,类可以从另一个类继承方法,属性和功能。 类可以进一步分类为子类和超类。

  • 子类 - 当一个类继承另一个类的属性,方法和功能被称为子类别。
  • 超类 - 包含从其自身继承其他类的属性,方法和函数的类称为超类。

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,因此程序将不允许创建子类,并且抛出错误。