The Swift Programming Language学习笔记(十二)——方法
方法
结构体和枚举能够定义方法是Swift与C/Objective-C的主要区别之一。在Objective-C中,类是唯一能定义方法的类型。但在Swift中,你不仅能选择是否要定义一个类/结构体/枚举,还能灵活地在你创建的类型(类/结构体/枚举)上定义方法。 实例方法
实例方法要写在它所属的类型的前后大括号之间。实例方法能够隐式访问它所属类型的所有的其他实例方法和属性。实例方法只能被它所属的类的某个特定实例调用。实例方法不能脱离于现存的实例而被调用。和调用属性一样,用点语法(dot syntax)调用实例方法 class Counter { var count = 0 func increment() { ++count } func incrementBy(amount: Int) { count += amount } func reset() { count = 0 } } let c = Counter() c.increment() c.incrementBy(10) c.reset()
方法的局部参数名称和外部参数名称函数参数可以同时有一个 Swift中的方法和Objective-C中的方法极其相似。像在Objective-C中一样,Swift中方法的名称通常用一个介词指向方法的第一个参数,比如: 具体来说,Swift默认仅给方法的第一个参数名称一个局部参数名称;默认同时给第二个和后续的参数名称局部参数名称和外部参数名称。这个约定与典型的命名和调用约定相适应,与你在写Objective-C的方法时很相似。这个约定还让富于表达性的方法在调用时不需要再限定参数名称。 class Counter { var count: Int = 0 func incrementBy(amount: Int,numberOfTimes: Int) { count += amount * numberOfTimes } } let c = Counter() c.incrementBy(5,numberOfTimes: 4) print(c.count)
默认情况下,Swift只把 你不必为第一个参数值再定义一个外部变量名:因为从函数名 在Swift中,定义方法使用了与Objective-C同样的语法风格,并且方法将以自然且富于表达性的方式被调用。 修改方法的外部参数名称有时为方法的第一个参数提供一个外部参数名称是非常有用的,尽管这不是默认的行为。你自己可以为第一个参数添加一个显式的外部名称。相反,如果你不想为方法的第二个及后续的参数提供一个外部名称,可以通过使用下划线(_)作为该参数的显式外部名称,这样做将覆盖默认行为。 self属性类型的每一个实例都有一个隐含属性叫做 实际上,你不必在你的代码里面经常写 使用这条规则的主要场景是实例方法的某个参数名称与实例的某个属性名称相同的时候。在这种情况下,参数名称享有优先权,并且在引用属性时必须使用一种更严格的方式。这时你可以使用 struct Point {
var x = 0,y = 0
func isTheSameX(x: Int) -> Bool {
print("(self.x)")
print("(x)")
return self.x == x
}
func isTheSameX2(x: Int) -> Bool {
print("(x)")
return x == x
}
}
let p = Point(x: 1,y: 2)
print(p.isTheSameX(3))
print(p.isTheSameX2(3))
/*
1
3
false
3
true
*/
上面的代码中,如果不使用 在实例方法中修改值类型结构体和枚举是值类型。默认情况下,值类型的属性不能在它的实例方法中被修改。 但是,如果确实需要在某个特定的方法中修改结构体或者枚举的属性,可以为这个方法选择可变( struct Point {
var x = 0,y = 0
mutating func a(m: Int,n: Int) { // 该方法修改了这个点,而不是返回一个新的点。
x += m
y += n
}
}
var a = Point(x: 1,y: 1) // 必须声明为变量!
a.a(5,n: 6)
print(a) // Point(x: 6,y: 7)
不能在结构体类型的常量(a constant of structure type)上调用可变方法,因为其属性不能被改变,即使属性是变量属性, 在可变方法中给self赋值可变方法能够赋给隐含属性 struct Point {
var x = 0,n: Int) { // 创建一个新的实例返回给self
self = Point(x: x + m,y: y + n)
}
}
var a = Point(x: 1,y: 1) // 必须声明为变量!
a.a(5,y: 7)
枚举的可变方法可以把 enum TriStateSwitch {
case Off,Low,High
mutating func next() -> TriStateSwitch {
switch self {
case .Off:
self = .Low
case .Low:
self = .High
case .High:
self = .Off
}
return self
}
}
var t = TriStateSwitch.Off // 必须声明为变量!
print(t.next()) // Low
print(t.next()) // High
print(t.next()) // Off
上面代码中,开关在不同的电源状态( 类型方法实例方法是被某个类型的实例调用的方法。你也可以定义在类型本身上调用的方法,这种方法就叫做 注意,在Objective-C中,你只能为Objective-C的类类型(classes)定义类型方法(type-level methods)。在Swift中,你可以为所有的类、结构体和枚举定义类型方法。每一个类型方法都被它所支持的类型显式包含。类型方法和实例方法一样用点语法调用。但是,只能在类型上调用这个方法。 在类型方法的方法体(body)中, 一般来说,在类型方法的方法体中,任何未限定的方法和属性名称,可以被本类中其他的类型方法和类型属性引用。一个类型方法可以直接通过类型方法的名称调用本类中的其它类型方法,而无需在方法名称前面加上类型名称。类似地,在结构体和枚举中,也能够直接通过类型属性的名称访问本类中的类型属性,而不需要前面加上类型名称。 /** * 文档上的一个名为LevelTracker结构体。它监测玩家的游戏发展情况(游戏的不同层次或阶段)。这是一个单人游戏,但也可以存储多个玩家在同一设备上的游戏信息。游戏初始时,所有的游戏等级(除了等级 1)都被锁定。每次有玩家完成一个等级,这个等级就对这个设备上的所有玩家解锁。LevelTracker结构体用类型属性和方法监测游戏的哪个等级已经被解锁。它还监测每个玩家的当前等级。 */
struct LevelTracker {
static var highestUnlockedLevel = 1
static func unlockLevel(level: Int) {
if level > highestUnlockedLevel { highestUnlockedLevel = level }
}
static func levelIsLocked(level: Int) -> Bool {
return level <= highestUnlockedLevel
}
var currentLevel = 1
mutating func advanceToLevel(level: Int) -> Bool {
if LevelTracker.levelIsLocked(level) {
currentLevel = level
return true
} else {
return false
}
}
}
class Player {
var tracker = LevelTracker()
let playerName: String // 这里的初始化和下面的init只能存在一个
func completeLevel(level: Int) {
LevelTracker.unlockLevel(level + 1)
tracker.advanceToLevel(level + 1)
}
init(playerName: String) {
self.playerName = playerName
}
}
let p1 = Player(playerName: "Tim")
p1.completeLevel(1)
print(p1.tracker.currentLevel) // 2
print(LevelTracker.highestUnlockedLevel) // 2
let p2 = Player(playerName: "Kate")
if p2.tracker.advanceToLevel(10) {
print("解锁成功!")
} else {
print("解锁失败!") // 解锁失败!
}
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |