文章目录
  1. 1. 1、概要
  2. 2. 2、实例方法
    1. 2.1. self属性
    2. 2.2. mutating关键字
  3. 3. 3、类型方法

1、概要

方法(Method)就是绑定到特定类型(类,结构体,枚举都可以)的函数(Function)。在Objective-C中,只有类能定义方法,而在Swift中,类,结构体和枚举都可以定义方法。
方法也可以定义为类型方法,跟实例方法区分,类似于Swift中的类方法。

2、实例方法

定义实例方法的时候,主要注意Swift对参数命名的默认处理方式。为了兼容之前Cocoa Objective-C API的定义方式,Swift这种默认的参数命名方式发挥了作用。当你看到一个Objective-C API方法时,可以立即写出来,对应的Swift方法。这在后面的文章中专门来谈。
Swift中对方法的命名的默认规则有以下几条:

  • 第一个参数默认没有外部参数名称,也就是说,第一个参数是怎么定义的,就是保持本身的语意
  • 第二个参数开始,外部参数名称默认为局部参数名称,也就是说,只有局部参数名称的情况下,Swift自动加上跟局部参数名称一样的外部参数名称
  • 也可以改变这种默认行为,改变方式跟函数的用法相同。例如:显式地给第一个参数加上外部参数名称;或者对第二个参数加上_,显式地要求不提供外部参数名称

规则解释起来比较抽象,还是看具体的例子,好理解。。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
class Counter
{
var count = 0
//没有参数,相安无事
func increment()
{
count++
}
//一个参数的情况下,不需要使用外部参数命名
func incrementBy(amount: Int)
{
count += amount
}
// 显式指定外部参数命名,覆盖默认行为
func addValueTo(value amount: Int)
{
count += amount
}
// 2个参数情况下,第二个参数默认指定外部参数命名second
//如果使用addTwiceWithExternalImplied(1, 2)
//会编译错误:Missing agrument label 'second:' in call
func addTwiceWithExternalImplied(first: Int, second: Int)
{
count += first
count += second
}
//2个参数情况下,显式指定外部参数名称
func addTwiceWithExternalSpecified(a first: Int, b second: Int)
{
count += first
count += second
}
//2个参数情况下,显式指定第一个外部参数名称
func addTwiceWithExternalSpecified2(#first: Int, second: Int)
{
count += first
count += second
}
//2个参数情况下,屏蔽掉第二个默认的外部参数名称
func addTwiceWithExternalSpecified3(first: Int, _ second: Int)
{
count += first
count += second
}
}
//对应定义的函数调用
var counter = Counter()
counter.increment()
counter.incrementBy(4)
counter.addValueTo(value: 4)
counter.addTwiceWithExternalImplied(50, second: 4)
counter.addTwiceWithExternalSpecified(a: 50, b: 4)
counter.addTwiceWithExternalSpecified2(first: 10, second: 10)
counter.addTwiceWithExternalSpecified3(10, 10)
counter.count

self属性

类型的每一个实例都拥有一个隐藏属性self,来表示这个实例本身。类似与C++中的this,与Objective-C中的self一样。可以在实例方法中通过self访问实例属性和方法。self一般用在消除歧义的地方,比如一个方法的传入参数名和类型中属性名称相同的情况下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Point
{
var x: Int = 10
func setX(x: Int)
{
//使用参数x赋值给类中存储属性x
self.x = x
}
func increment()
{
//这里可以不使用self,因为没有歧义
self.x++
}
}

mutating关键字

值类型结构体和枚举的实例方法无法修改属性的值。如果需要修改,需要使用mutating关键字修饰实例方法,这时这个实例方法就可以修改属性值了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
struct Point2
{
var x: Int = 10
//如果不使用mutating
//会编译错误:cannot assign to 'x' in 'self'
mutating func setX(x: Int)
{
self.x = x
}
}
var point = Point2(x: 3)
point.setX(10)
//定义一个常量结构体实例,调用mutating方法会报编译错误:
//Immutable value of type 'Point2'
//only has mutating members named 'setX'
let fixedPoint = Point2(x: 3)
fixedPoint.setX(4)
//类中不需要使用mutating
class PointClass
{
var x: Int = 1
func setX(x: Int)
{
self.x = x
}
}
var pointClass = PointClass()
point.setX(10) //x变为10

另外,在值类型mutating修饰的方法中,可以对self进行赋值,这样会变成另外一个新的实例。

以下是结构体的例子:

1
2
3
4
5
6
7
8
9
struct Point3
{
var x = 0
mutating func replaceMe(newX: Int)
{
self = Point3(x: 3)
}
}

以下是枚举的例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
enum TriStateSwitch
{
case Off, Low, High
mutating func next()
{
switch self
{
case Off:
self = Low
case Low:
self = High
case High:
self = Off
}
}
}
var stat = TriStateSwitch.low
stat.next() //现在等于.High
stat.next() //现在等于.Off

3、类型方法

类型方法和类型属性定义方法有点相似,值类型使用static关键字,引用类型使用class关键字,另外一些特性点如下:

  • 类型方法中,也可以使用self关键字,这个时候代表这个类型本身,而不是一个具体的类型实例
  • static也可以修饰类中的方法,这个时候表示不能继承的类型方法,而class修饰的类型方法,是可以在子类中重载的
1
2
3
4
5
6
7
8
9
10
class SomeOtherClass
{
class func isGreaterThan100(value: Int) -> Bool
{
return value > 100
}
}
//类型方法调用方式如下:
SomeOtherClass.isGreaterThan100(105)
文章目录
  1. 1. 1、概要
  2. 2. 2、实例方法
    1. 2.1. self属性
    2. 2.2. mutating关键字
  3. 3. 3、类型方法