
mutating
结构体和枚举类型,默认情况下,值类型的属性不能被自身的实例方法修改
如果需要修改,需要在方法前添加mutating关键字
struct Point {
var x = 0.0, y = 0.0
mutating func moveBy(deltaX : Double, deltaY : Double) {
x += deltaX
y += deltaY
}
}
枚举也是同理的
enum StateSwitch {
case low,middle,high
mutating func next() {
switch self {
case .low:
self = .middle
case .middle:
self = .high
case .high:
self = .low
}
}
}
不加mutating是会报错的
discardableResult
struct Point {
var x = 0.0, y = 0.0
mutating func moveBy(deltaX: Double) -> Double{
x += deltaX
y += deltaY
}
}
在上述代码中,方法会返回一个Double值
如果我们在调用的时候
var p = Point()
p.moveBy(deltaX:10) // 这行是会出现黄色警告⚠️,告诉你这个返回值,你没有使用
如果你在方法前加入了@discardableResult
struct Point {
var x = 0.0, y = 0.0
@discardableResult mutating func moveBy(deltaX: Double) -> Double{
x += deltaX
y += deltaY
}
}
这样就不会有那个警告出现了
下标
使用subscript可以给任意类型(枚举,类,结构体)增加下标功能,有些地方也称之为:下标脚本
subscript的语法类似于实例方法,计算属性,本质就是方法(函数)
class Point {
var x = 0.0
var y = 0.0
subscript(index:Int) -> Double {
set {
if index == 0 {
x = newValue
}else if index == 1 {
y = newValue
}
}
get {
if index == 0 {
return x
}else if index == 1 {
return y
}
return 0.0
}
}
}
在调用的时候
var p = Point()
p[0] = 1.0 // set方法
p[1] = 2.0 // set方法
print(p[0]) // get方法
用起来跟数组的感觉是一样的
1.subscript中定义的返回值决定了get方法set方法返回的类型
2.subscript可以接受多个参数,并且类型任意
下标的细节
class Point {
var x = 0.0
var y = 0.0
subscript(index:Int) -> Double {
get {
if index == 0 {
return x
}else if index == 1 {
return y
}
return 0.0
}
}
}
1.subscript可以没有set方法,但不能没有get方法
2.如果只有get方法,相当于是只读属性,不能修改
2.如果只有get方法,可以省略get
class Point {
var x = 0.0
var y = 0.0
subscript(index:Int) -> Double {
if index == 0 {
return x
}else if index == 1 {
return y
}
return 0.0
}
}
可以设置参数标签
class Point {
var x = 0.0
var y = 0.0
subscript(index i:Int) -> Double {
set {
if i == 0 {
x = newValue
}else if i == 1 {
y = newValue
}
}
get {
if i == 0 {
return x
}else if i == 1 {
return y
}
return 0.0
}
}
}
var p = Point()
p[index: 1]
下标可以是类方法
class Point {
var x = 0.0
var y = 0.0
static subscript(index v1:Int,index v2:Int) -> Double {
set {
}
get {
return 0.0
}
}
}
Point[index: 10, index: 20]

结构体,类作为返回值的对比
如果返回值是一个结构体,是需要补上set方法,因为结构体是值类型,是需要进行拷贝的,既然拷贝了新的一份,那么就无法访问到了原来的那一份,而类是引用类型,可以根据指针访问到。
重写类型方法、下标
class Animal {
class func speak() {
print("animal speak")
}
class subscript(index i:Int) -> Int {
return i;
}
}
class Cat : Animal {
override class func speak() {
super.speak()
print("cat speak")
}
override class subscript(index i: Int) -> Int {
return super[index: i] + 1
}
}
在上述代码中,父类的类方法,如果是被class修饰的,在子类中是可以重写,如果父类的类方法是被static修饰的,在子类是不能被重写的,如下图的展示

但是,如果子类可以把父类的方法重写为static
class Animal {
class func speak() {
print("animal speak")
}
class subscript(index i:Int) -> Int {
return i;
}
}
class Cat : Animal {
override static func speak() {
super.speak()
print("cat speak")
}
override class subscript(index i: Int) -> Int {
return super[index: i] + 1
}
}
在上述代码中,Cat的speak方法,被修饰成了static,并不会报错,但是继承Cat的子类,就无法重写这个方法了
重写实例属性



属性观察器
可以在子类中为父类增加属性观察器
class Circle {
var radius: Int = 1
}
class SubCircle : Circle {
override var radius:Int {
willSet {
print("SubCircleWillSet",newValue)
}
didSet {
print("SubCircleDidSet",oldValue,radius)
}
}
}

Final
1.被final修饰的方法、下标、属性,禁止被重写
2.被final修饰的类,禁止被继承
class ClassA {
class func func1() -> String {
return "func1"
}
static func func2() -> String {
return "func2"
}
class final func func3() -> String {
return "func3"
}
}
class ClassB : ClassA {
override class func func1() -> String {
return "func1 in ClassB"
}
// ERROR: Cannot override static method
override static func func2() -> String {
return "func2 in ClassB"
}
// ERROR: Class method overrides a 'final` class method
override class func func3() -> String {
return "func3 in ClassB"
}
}
网友评论