方法(Method)
枚举、结构体、类都可以定义实例方法、类型方法
实例方法
(Instance Method):通过实例调用
类型方法
(Type Method): 通过类型调用,用static
或者class
关键字定义
self
在实例方法中代表实例
在类型方法中代表类型
class Car {
static var count = 0
init() {
Car.count += 1
}
static func getCount() -> Int {
count
}
}
let c0 = Car()
let c1 = Car()
let c3 = Car()
/// 打印结果:3
print(Car.getCount())
mutating
结构体和枚举是值类型,默认情况下,值类型的属性不能被自身的实例方法修改
在func关键字前加mutating
可以允许这种修改行为
struct Point {
var x = 0.0, y = 0.0
mutating func moveBy(detailX:Double,detailY:Double) {
/// func前必须要加mutating,否则编译器会报错
x += detailX
y += detailY
}
}
enum StateSwitch {
case low,middle,high
mutating func next() {
switch self {
case .low:
self = .middle
case .middle:
self = .high
case .high:
self = .low
}
}
}
@discardableResult
在func前面加个
@discardableResult
,可以消除:函数调用后返回值未被使用的警告
struct Point {
var x = 0.0, y = 0.0
@discardableResult mutating func moveX(detailX:Double) -> Double {
x += detailX
return x
}
}
var p = Point()
p.moveX(detailX: 10)
下标(subscript)
使用subscript可以给任意类型(
枚举、结构体、类
)增加下标功能
,有些地方也翻译为:下标脚本
subscript的语法类似于实例方法、计算属性、本质就是方法(函数)
subscript中定义的
返回值类型决定
了
get方法的返回值类型
set方法中newValue的类型
subscript 可以
接受多个参数,并且类型任意
subscript可以
没有set方法,但必须要有get方法
如果只有get方法,可以省略get
class Point {
var x = 0.0, 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
}
}
}
var p = Point()
p[0] = 11.1
p[1] = 22.2
print(p.x)
print(p.y)
print(p[0])
print(p[1])
可以
设置参数标签
class Point {
var x = 0.0 , y =0.0
subscript(index i:Int) -> Double {
if i==0 {
return x
}
else if i==1 {
return y
}
return 0
}
}
var p = Point()
p.y = 22.2
print(p[index: 1])
下标可以使类型方法
class Sum {
static subscript(v1:Int,v2:Int) -> Int {
return v1 + v2
}
}
print(Sum[10,20])
class Point {
var x = 10, y = 10
}
class PointManager {
var point = Point()
subscript(index:Int) -> Point {
/// 不一样的是:这里的newValue是point类型,而不是传进来的Int类型
set {point = newValue}
get {point}
}
}
var pm = PointManager()
/// 底层: pm[0] = Point(x:11,y:pm[0].y)
pm[0].x = 11
pm[0].y = 22
要特别注意的:如果Point是结构体struct,以下的方法会报错
struct Point {
var x = 10, y = 10
}
class PointManager {
var point = Point()
subscript(index:Int) -> Point {
/// 解决方法:这样赋值之后,point就会变成另外一个新的值
/// set{ point = newValue}
get {point}
}
}
var pm = PointManager()
/// 以下的两个方法会报错
/// 因为Point 是值类型(赋值是内容拷贝),
///而通过pm[0]获取到的是PointManager对象point属性的一个拷贝的值,所以设置其x的值是没意义的,也不行
/// 解决方法:下标添加一个set方法(如上代码)
pm[0].x = 11
pm[0].y = 22
接收
多个参数
的下标
class Grid {
var data = [
[0,1,2],
[3,4,5],
[6,7,8]
]
subscript(row:Int,column:Int) ->Int {
set {
guard row>=0 && row < 3 && column >= 0 && column < 3 else {
return
}
data[row][column] = newValue
}
get {
guard row>=0 && row < 3 && column >= 0 && column < 3 else {
return 0
}
return data[row][column]
}
}
}
var grid = Grid()
grid[0,1] = 77
grid[1,2] = 88
print(grid.data)
继承
值类型(结构体、枚举)不支持继承,只有类支持继承
没有父类的类,称为:基类
Swift并没有像OC、Java那样的规定:任何类最终都要继承自某个基类
子类可以重写父类
的下标
、方法
、属性
,重写必须要加上override
关键字
内存结构(
堆空间
的内存分配都是16的倍数
)
Swift与OC不同的是:Swift对象前16个字节
分别存放的是类的信息
和引用计数
重写
实例方法、下标
class Animal {
func speak() {
print("Animal speak")
}
subscript(index:Int) ->Int {
return index
}
}
class Cat: Animal {
override func speak() {
super.speak()
print("Cat speak")
}
override subscript(index: Int) -> Int {
return super[index] + 1
}
}
重写
类型方法、下标
被class
修饰的类型方法、下标
,允许
被子类重写
被static
修饰的类型方法、下标
,不允许
被子类重写
class Animal {
class func speak() {
print("Animal speak")
}
class subscript(index:Int) ->Int {
return index
}
}
class Cat: Animal {
override class func speak() {
super.speak()
print("Cat speak")
}
override class subscript(index: Int) -> Int {
return super[index] + 1
}
}
/// 备注:原来用class修饰的类型方法,可以用static重写,本质不变都是类型方法
/// 影响的是:Dog其子类就不能再重写static修饰的类型方法
class Dog: Animal {
override static func speak() {
super.speak()
print("Cat speak")
}
override static subscript(index: Int) -> Int {
return super[index] + 1
}
}
重写属性
- 子类可以将父类的属性(存储、计算)
重写为计算属性
- 子类
不可以
将父类属性重写为存储属性
- 只能
重写var属性
,不能重写let属性
- 重写时,属性名、类型要一致
*子类
重写后的属性权限
不能小于父类属性的权限
(1)如果父类属性是只读的,那么子类重写后的属性可以是只读的,也可以是可读写的
(2)如果父类属性是可读写的,那么子类重写后的属性也必须是可读写的
# 重写实例属性
class Circle {
var radius : Int = 0
var diameter : Int {
set {
print("Circle setDiameter")
radius = newValue / 2
}
get {
print("Circle getDiameter")
return radius * 2
}
}
}
class SubCircle: Circle {
override var radius: Int {
set {
print("SubCircle setRadius")
super.radius = newValue > 0 ? newValue : 0
}
get {
print("SubCircle getRadius")
return super.radius
}
}
override var diameter: Int {
set {
print("SubCircle setDiameter")
super.diameter = newValue > 0 ? newValue : 0
}
get {
print("SubCircle getDiameter")
return super.diameter
}
}
}
var circle = SubCircle()
/// SubCircle setRadius
circle.radius = 6
/// SubCircle getDiameter
/// Circle getDiameter
/// SubCircle getRadius
/// 12
print(circle.diameter)
/// SubCircle setDiameter
/// Circle setDiameter
/// SubCircle setRadius
circle.diameter = 20
/// SubCircle getRadius
/// 10
print(circle.radius)
重写类型属性
*被class
修饰的计算类型属性
,可以被子类重写
*被static
修饰的类型属性(存储,计算)
,不可以被子类重写
///
类型的存储属性
是不能用class修饰
的
class Circle {
static var radius : Int = 0
class var diameter : Int {
set {
print("Circle setDiameter")
radius = newValue / 2
}
get {
print("Circle getDiameter")
return radius * 2
}
}
}
class SubCircle: Circle {
override class var diameter: Int {
set {
print("SubCircle setDiameter")
super.diameter = newValue > 0 ? newValue : 0
}
get {
print("SubCircle getDiameter")
return super.diameter
}
}
}
属性观察器
可以在子类中为父类属性(除了只读计算属性、let属性
)增加属性观察器
class Circle {
var radius : Int = 1
}�
class SubCircle: Circle {
override var radius: Int {
willSet {
print("SubCircle willSetRadius",newValue)
}
didSet {
print("SubCircle didSetRadius",oldValue,radius)
}
}
}
class Circle {
var radius : Int = 1 {
willSet {
print("Circle willSetRadius",newValue)
}
didSet {
print("Circle didSetRadius",oldValue,radius)
}
}
}
class SubCircle: Circle {
override var radius: Int {
willSet {
print("SubCircle willSetRadius",newValue)
}
didSet {
print("SubCircle didSetRadius",oldValue,radius)
}
}
}
var circle = SubCircle()
/// SubCircle willSetRadius 10
/// Circle willSetRadius 10
/// Circle didSetRadiu 1 10
/// SubCircle didSetRadius 1 10
circle.radius = 10
final
被final修饰的
方法、下标、属性
,禁止被重写
被final修饰的类
,禁止被继承