mutating 关键字
在结构体(值类型,枚举也适用)中,如果要修改自身的成员变量,不能直接修改,要加上mutating,或者不用结构体,直接用类。
struct Value{
var x = 0
var y = 0
mutating func change(x1:Int,y1:Int){
x = x + x1
y = y + y1
}
}
@discardableResult
Result of call to 'change(x1:y1:)' is unused 警告是说返回值可能没有使用,可以在方法之前加@discardableResult,表示返回值可使用也可以不使用,只是调用不会报警告,个人建议还是少用比较好,方法的目的性要明确,不然可能会误解。
**class** CountValue:NSObject{
**var** x = 0
**var** y = 0
**@discardableResult** **func** change(x1:Int,y1:Int) -> Int{
x = x + x1
y = y + y1
**return** x
}
}
let p = CountValue()
p.change(x1: 1, y1: 2)
subscript
subscript可以给任意类型添加下标,本质是方法,类似于数组使用,必须有get方法,可以没有set方法
**subscript**(index:Int)->Int{
**set**{
**if** index == 0{
**self**.x = newValue
}
**if** index == 1{
**self**.y = newValue
}
}
**get**{
**if** index == 0 {
**return** **self**.x
}
**if** index == 1 {
**return** **self**.y
}
**return** 0
}
}
**let** p = Point(x: 0, y: 0)
p[0] = 10
p[1] = 11
print(p.x,p.y) // 10 11
也可以为下标添加多个值,默认是实例方法
class PlueMethod {
static subscript (a:Int,b:Int)->Int{
return a + b
}
}
print(PlueMethod[10,20]) // 30
继承
值类型不支持继承,只有类才有继承。
swift不像oc每个类都有最终继承类,只要没有父类都是基类。
子类可以重写父类的下标,属性,方法。
子类继承父类,默认会获得父类的属性,会把父类的属性放到前面,内存会增加。
重写实例方法,只需要在也是一定要在方法前面加上override
重写类型方法,只有被class修饰的类型方法可以被子类重写,被static修饰的不行。
重写属性,只能重写成计算属性,不能重写成实例属性
只能重写var属性,不能重写let属性
子类重写父类,权限不能比父类小,父类可读可写,子类必须可读写,父类可读,子类可读也可以可读写。
如果是类型属性,只有计算类型属性可以被子类重写,存储类型属性不能被class修饰。
重写实例属性
**class** subCircle:CirCle{
**override** **var** radio: Double {
**set**{
**super**.radio = newValue
}
**get**{
print("get radio")
**return** **super**.radio
}
}
**override** **var** diameter: Double{
**set**{
print("set diameter")
**super**.diameter = newValue
}
**get**{
print("get diameter")
**return** **super**.diameter
}
}
}
注意,这里都是通过获取父类里的属性来修改的,如果不加super,默认就是self,如果改成self,会导致死循环,不断调用本类的set或者get方法。
属性观察器
可以为父类添加属性观察器,只读和let修饰的不能添加属性观察器,如果不想被子类继承,可以添加关键字final
父类没有属性观察器
父类有属性观察器
给子类设置一个值,调用顺序是子类的willget,父类的willget,父类的didiset,子类的didiset。
swift中多态的实现原理
通过对象地址找到这个对象所在堆空间的首地址,然后通过首地址找到关于这个类的类型信息,在类的类型信息中包含了方法的地址,然后通过固定偏移量找到这个方法地址。在程序编译完成以后,方法的地址就已经确定了,知道类要调用的方法是谁。