1. 方法的命名规则以及参数名规则:
1) 方法就是枚举、结构体、类中定义的“函数”,但是它跟函数在命名方面有很大的不同;
2) 首先看一下参数命名规则:
class A
{
func increBy(inc: Int, atIndex: Int) { }
}
// A().increBy(inc: 5, atIndex: 34) // 默认情况下不会为第一个参数设置外部参数名
// A().increBy(5, 23) // 第一个参数之后的所有参数必须有外部参数名,默认为和内部参数名相同,因此不需要加#
A().increBy(5, atIndex: 15) // OK!
class B
{
// 强行为第一个参数添加外部参数名,第二个参数使用#强调内外一致(其实是不必要的,编译器会警告)
// 第三个参数自己定义外部参数名
func increBy(#inc: Int, #atIndex: Int, oth one: Int) { }
}
B().increBy(inc: 23, atIndex: 94, oth: 23) // OK!
3) 参数规则看上去很古怪其实是为了配合函数的命名规则的:
i) 实际上函数的命名规则是任意的,只要符合标示符命名规则即可,但是Swift强调和建议使用其约定俗成的命名规则,并且如果使用该约定的规则就可以和参数命名规则很好的配合,是代码更加清晰明确;
ii) Swift建议函数以动词开头,最后一个单词或者倒数第二个单词为介词,之所以第一个参数可以没有外部参数名就是因为Swift建议函数名中的介词在表意上指向第一个参数,这样第一个参数即使没有外部名称意思也会非常明确,达到简洁明了的效果,比如上面的increBy(23, atIndex: 15),就是指以23为增长单位,对下标为15的位置的元素进行增长,这看上去非常自然明了;
iii) 同时,第一个以后的参数名Swift建议以介词开头,因为一般方法的参数都是方法作用的对象或作用的介质,因此都以介词打头会非常明了,由于第一个参数作用的介词在函数名中已经体现了,而后面的参数作用的介词在函数名中并不存在,因此Swift强制要求之后的参数必须要有外部参数名(并且建议外部参数名都以介词打头),这样就保证了方法的每个参数的含义和作用都非常清晰(只看接口就能看懂),C++就不如Swift的这点了,C++接口都没有参数名,而且参数有那么多,让人很头晕,大大增加了程序员的记忆压力;
2. self以及结构体和枚举方法的变异:
1) 使用self(即和C++的this一样)消除同名参数歧义,以及必要时访问自身(很明显只能用于实例而不能用于静态):
class A
{
var a: Int = 5
var b: Int = 3
func change(a: Int, b: Int)
{
self.a = a
self.b = b
}
}
2) Swift默认在结构体和枚举中的方法不能修改属性的!这就体现出来Swift对结构体的定位了,Swift希望结构体的方法不对属性进行修改而仅仅是用来进行输出信息等操作,因此Swift将结构体定位成一种小型的数据包,如果硬要修改就只要把方法定义成变异类型就行了,使用关键字mutating修饰即可:
struct A
{
var a: Int = 5
func change(var aa: Int)
{
aa = 5 // 要让参数可修改加var即可
// a = aa // 但是存储属性是默认不能在方法中修改的!但是可以在外部通过.a = newa的方式修改!
}
mutating func change2(var aa: Int) // 声明称变异方法后就可以在方法中修改存储属性
{
// 这样参数和存储属性都可以修改了
aa = 10
a = aa // 前提是a必须是var
}
}
对于枚举是一样的!
3) 不仅可以对存储属性修改,还可以修改self的值(注意,结构体和枚举都是值类型的):
enum Test: String
{
case a = "a"
case b = "b"
case c = "c"
mutating func next()
{
switch self
{
case .a: self = .b
case .b: self = .c
case .c: self = .a
}
}
}
var test = Test.a
println(test.rawValue) // a
test.next()
println(test.rawValue) // b
test.next()
println(test.rawValue) // c
test.next()
println(test.rawValue) // a
4) 变异仅仅针对枚举和结构体,对于类来说想改就改的,前面已经出现过很多次了:
class A
{
var a: Int = 5
func change(aa: Int)
{
a = aa // 对于类来说想改就改,其实之前都已经演示过很多回了!
}
}
3. 静态方法:
1) 和静态属性一样,属于类型不属于示例,只能通过类型名调用的方法;
2) 同样,静态方法可以调用其它静态方法或属性并且不需要类型名,但静态方法不可以调用任何非静态的成员,而静态成员可以随意调用静态方法以及访问静态属性,但是调用和访问的时候必须使用类型名;
3) 结构体和枚举还是使用static修饰方法,而类使用class修饰,这里就以类作为例子好了:
class A
{
class var a: Int {
return 5
}
class func geta() -> Int {
return a
}
var b: Int {
return A.geta() // 非静态属性或方法中调用静态属性必须要通过类型名!否则会报错
}
}
4) 在静态方法中也可以使用self,只不过这里的self实质类型本身而不是指实体,一般不建议使用(在其它语言中是不支持这种使用方法的):
并且在结构体和类中,虽然默认不能修改实例属性,但是可以随意修改静态属性而不需要变异!
struct A
{
static var a: Int = 5
// 虽然默认普通存储属性在方法中不能修改
// 但是静态属性是可以随意修改的!
static func change() // 通过静态方法修改静态存储属性
{
self.a = 10 // 这里的self表示A类型自身
}
func change2() // 通过实例方法修改静态存储属性
{
A.a = 10
}
}