继承
继承是一种基本行为:子类继承父类方法,属性和其他特性。子类可以重写父类的方法,属性。继承将类与Swift中的其他类型区分开来。
类还可以将属性观察者添加到继承的存储属性或计算属性上。
定义一个基类
基类:定义的任何不从其他类继承的类。Swift中的类在不指定父类的情况下,是不会从通用基类继承,这种情况下构建的类便是开发者定义的基类。
class BaseClass {
//....基类的方法,属性等定义
}
子类
子类:在现父类基础上构建的新类。子类继承父类的方法,属性和其他特征,并进行差异化操作。
class SubClass: BaseClass {
//...继承自`BaseClass`的子类
}
重写
重写:子类提供父类的实例方法,类型方法,实例属性,类型属性或下标的自定义实现。
重写的实现方式:子类要覆盖的继承父类的特性属性或方法前使用override
关键字。
访问父类的方法,属性和下标
在重写父类的方法,属性和下标时,使用super
前缀可以承继父类对于方法,属性和下标的实现。
class BaseClass {
//....基类的方法,属性等定义
var something: String {
get {
return "i from super"
}
}
func doSomething() -> Void {
}
subscript(index:Int)->String {
return "QiShare"
}
}
class SubClass: BaseClass {
//...继承自`BaseClass`的子类
override var something: String {
return super.something + "+override" //!< 调用输出:i from super+override
}
override func doSomething() {
super.doSomething()
}
override subscript(index:Int)->String {
return super[1] + "/subClass" //!< 调用输出:QiShare/subClass
}
重写属性
可以覆盖继承的实例或类型属性,为该属性提供自定义的getter
和setter
,也能添加属性观察者。子类无法知道继承的属性是否计算或存储属性,但知道继承的属性名称和类型。故重写属性时需明确属性的名称和类型。
1. 重写属性的Getter
和 Setter
方法:
关于重写属性的Getter
和 Setter
,官网描述:
You can provide a custom getter (and setter, if appropriate) to override any inherited property, regardless of whether the inherited property is implemented as a stored or computed property at source。译文:无论继承的属性是在父类中是存储属性还是计算属性,子类都可以提供自定义
getter
,也可以在场景适用情况下提供setter
,用以重写属性
但是在实际的操作中发现:
• 继承自父类的存储属性不能被重写。重写时报错:Cannot override with a stored property 'something'
。错误示范如下:
//父类声明常量属性
let something: String = "QiShare"
//子类重写常量属性:报错:`Cannot override with a stored property 'something'`
override let something: String {
get {
return "sub+QiShare"
}
}
• 继承自父类的变量属性,非计算属性,子类在重写该属性时需要同时提供setter
和getter
。否则编译器报错:Cannot override mutable property with read-only property 'something'
。正确示范如下:
//父类声明变量属性
var something: String = ""
//或
var something: String?
//子类重写变量属性
override var something : String {
get {
return "子类的实现"
}
set{
}
}
• 通过重写计算属性Getter
和 Setter
方法,子类可将继承自父类的read-only
属性变为read-write
属性。示例如下:
//父类声明`read-only`属性
var something: String {
get {
return "i from super"
}
}
//子类重写后变为`read-write`属性
private var _temp :String = ""
override var something: String {
get {
return super.something + _temp //!< 调用输出:i from super+override
}
set {
_temp = newValue + "subClass override setter"
}
}
//实际调用,确实如此
let base = BaseClass()
//base.something = "这句话会报错,因为`sothing`在基类中是只读属性"
let sub = SubClass()
sub.something = "子类重写后" //!< i from super子类重写后subClass override setter
• 通过重写计算属性Getter
和 Setter
方法,不能将继承自父类的read-write
属性变为read-only
。个人理解:子类可以增加属性功能,但不能减少属性功能。反其道而行之,编译器报错:Cannot override mutable property with read-only property 'something'
• 计算属性不管是read-write
还是read-only
都需要使用var
关键字来声明为变量属性。计算属性在组成上由getter
和一个可选的setter
组成的,即:不管setter
有没有,getter
都必须有。也因此,若是我们重写了setter
方法则必须重写getter
方法。基于这种情况getter
方法的重写,有时是基于语法的组合体,本质上其实和父类是一样的,那么我们便可以在getter
方法中使用super
前缀来承继父类的调用。
2. 重写属性的观察者:
• 属性可观察的前提是该属性是可变的,故不能在继承的存储属性和read-only
属性中添加willSet
和didSet
。反其道而行之,实际操作中编译器也会报错:Cannot observe read-only property 'something'; it can't change
。
• 继承的read-write
属性,不能重写setter
方法的同时,重写或者添加属性观察器。反其道而行之,在实际操作中编译器会报错:didSet
或 willSet
cannot be provided together with a
setter
或 getter
。
防止重写
使用final
关键字防止方法,属性或下标被子类重写。具体使用:final var
,final func
,final class func
和final subscript
。
- 父类使用
final
关键字修饰过的方法,属性或下标,子类重写时编译器便会报错。 - 在类扩展中使用
final
关键字修饰过的方法,属性或下标也同样生效。 - 在类定义时的class关键字之前使用
final
关键字,来将整个类的方法,属性或下标标记为子类不可重写。
参考资料:
swift 5.1官方编程指南
网友评论