Swift - 方法重写



重写是面向对象编程语言中一个非常常见的概念。使用重写,我们可以重新实现超类中的方法或属性在子类中。它允许我们扩展继承的行为。在重写方法或属性时,我们提供子类中的新实现,而不是使用超类中的实现。在 Swift 中,我们可以重写超类的方法或属性。

访问超类的方法、属性和下标

super”关键字用作前缀来访问在超类中声明的方法、属性和下标。

方法重写 访问方法、属性和下标
方法 super.somemethod()
属性 super.someProperty()
下标 super[someIndex]

Swift 中重写的规则

以下是一些你在重写时应该遵循的规则:

  • 子类中重写的方法或属性必须具有与超类中相同的签名(名称、参数和返回类型)。

  • 使用super关键字从重写方法中的超类调用重写的实现。

  • 使用override关键字重写属性。我们可以重写存储属性和计算属性。

  • 重写方法或属性的访问级别不能比基类中重写方法或属性的访问级别更严格。不允许使用私有方法重写公共方法。因此,在重写之前始终检查访问修饰符。

Swift 中的方法重写

在 Swift 中,我们可以重写方法。重写方法意味着子类可以为在基类中已定义的方法提供不同的实现。或者我们可以说,我们可以在子类中自定义超类方法的行为。

子类中重写的方法必须具有与基类相同的签名(名称、参数和返回类型),编译器将根据对象的类型确定调用哪个方法。此外,子类中重写方法的访问级别必须与超类中方法的访问级别相同或更宽松。

重写方法是通过在子类中使用override关键字来定义的。此关键字放置在函数定义的开头。它告诉编译器该方法将重写超类的方法。如果我们没有指定override关键字,则编译器将给出错误。

语法

以下是方法重写的语法:

override func methodName(Parameters) -> returntype {
   Statement
   return parameters
}

示例

Swift 方法重写的程序。

// Super class
class cricket {
   // Method
   func show() {
      print("Welcome to Swift Super Class")
   }
}

// Sub class
class tennis: cricket {
   // Overriden Method
   override func show() {
      print("Welcome to Swift Sub Class")
   }
}

// Creating instance of subclass
let tennisinstance = tennis()

// Accessing the override method
tennisinstance.show()

输出

它将产生以下输出:

Welcome to Swift Sub Class

属性重写

Swift 支持属性重写。与方法重写一样,属性重写也为子类提供了一种自定义在基类中已定义的属性实现的方式。我们可以说,使用属性重写,我们可以为该属性提供我们自己的 getter 和 setter,或者添加属性观察器,这使得重写属性能够观察属性值何时更改。

子类中重写属性的类型必须与基类中属性的名称和类型相同。这样编译器就可以根据对象的类型确定调用哪个属性(超类属性或重写属性)。子类中重写方法的访问级别必须与超类中属性的访问级别相同或更宽松。

重写属性是通过在子类中使用override关键字来定义的。此关键字放置在属性定义的开头。它告诉编译器该属性将重写超类的属性。如果我们没有指定override关键字,则编译器将给出错误。

语法

以下是属性重写的语法:

override var propertyName: type{
   // Statement
}

示例

Swift 属性重写的程序。

// Superclass
class mySuperClass {

   // Property
   var language: String{
      return "C++"
   }
}
// Subclass
class mySubClass: mySuperClass {

   // Override Property
   override var language: String{
      return "Swift"
   }
}

// Creating an instance of a subclass
let obj = mySubClass()

// Accessing the overridden property
print(obj.language)

输出

它将产生以下输出:

Swift

重写属性 getter 和 setter

Swift 允许用户重写子类属性的 getter 和 setter,无论该属性是存储属性还是计算属性。重写属性的名称和类型必须与基类中存在的属性相同。这样编译器就知道你正在重写基类的属性。

在 Swift 中,我们可以通过在子类中重写时同时提供 getter 和 setter,将只读继承属性表示为读写属性。而我们不允许将读写继承属性表示为只读属性。当为重写属性定义 setter 时,用户也必须定义 getter。如果我们不希望在重写 getter 中修改继承属性的值,则可以使用 'super.PropertyName' 从 getter 传递继承的值,其中 PropertyName 表示重写属性的名称。

示例

Swift 重写属性 getter 和 setter 的程序。

// Base Class
class Circle {
   var radius = 12.5
    
   // Property with getter
   var area: String {
      return "of rectangle for \(radius) "
   }
}

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

// Creating instance
let rect = Rectangle()

// Accessing the properties
rect.radius = 25.0
rect.print = 3
print("Radius \(rect.area)")

输出

它将产生以下输出:

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

阻止 Swift 中的重写

Swift 提供了一个特殊的关键字来阻止重写方法、属性、下标甚至类,这个关键字被称为final关键字。final 关键字明确指示指定的 方法、属性、下标或类不能被子类重写。如果用户仍然尝试重写,则编译器将给出错误。

final 关键字始终用于方法、属性、下标或类的声明之前。

语法

以下是阻止重写的语法:

// For methods
final func methodName(Parameters) -> returntype{}

// For property
final var propertyName : type

// For subscript
final subscript(index: Int)->Elemnt{}

// For class
final class className{}

示例

阻止重写的 Swift 程序。

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

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

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

错误

main.swift:12:17: error: property overrides a 'final' property
   override var area: String {
                ^
main.swift:4:8: note: overridden declaration is here
   var area: String {
       ^
main.swift:10:7: error: inheritance from a final class 'Circle'
class Rectangle: Circle {
      ^
main.swift:21:17: error: ambiguous use of 'area'
print("Radius \(rect.area)")
                ^
main.swift:12:17: note: found this candidate
   override var area: String {
                ^
main.swift:4:8: note: found this candidate
   var area: String {
       ^

由于超类声明为 'final',其数据类型也声明为 'final',因此程序不允许进一步创建子类,并将抛出错误。

广告