Swfit里的方法 Methods

目录

实例方法 (Instance Methods)

self 属性

在实例方法中修改值类型(可变方法,mutating关键字修饰func)

在可变方法中给 self 赋值

类型方法

总结


方法是与某些特定类型相关联的函数。类、结构体、枚举都可以定义实例方法;实例方法为给定类型的实例封装了具体的任务与功能。类、结构体、枚举也可以定义类型方法;类型方法与类型本身相关联。类型方法与 Objective-C 中的类方法(class methods)相似

结构体和枚举能够定义方法是 Swift 与 C/Objective-C 的主要区别之一。在 Objective-C 中,类是唯一能定义方法的类型

实例方法 (Instance Methods)

实例方法是属于某个特定类、结构体或者枚举类型实例的方法。实例方法提供访问和修改实例属性的方法或提供与实例目的相关的功能,并以此来支撑实例的功能。实例方法的语法与函数完全一致

class Counter {
    var count = 0
    func increment() {
        count += 1
    }
    func increment(by amount: Int) {
        count += amount
    }
    func reset() {
        count = 0
    }
}

函数参数可以同时有一个局部名称(在函数体内部使用)和一个外部名称(在调用函数时使用)

self 属性

类型的每一个实例都有一个隐含属性叫做 selfself 完全等同于该实例本身。

上面例子中的 increment 方法还可以这样写

func increment() {
    self.count += 1
}

不必在你的代码里面经常写 self。不论何时,只要在一个方法中使用一个已知的属性或者方法名称,如果你没有明确地写 self,Swift 假定你是指当前实例的属性或者方法。上面的 Counter 中已经示范

struct Point {
    var x = 0.0, y = 0.0
    func isToTheRightOf(x: Double) -> Bool {
        参数名同属性时,比属性有优先权。属于必须self.访问
        return self.x > x
    }
}

不使用 self 前缀,Swift会认为 x 的两个用法都引用了名为 x 的方法参数。

在实例方法中修改值类型(可变方法,mutating关键字修饰func)

结构体和枚举是值类型。默认情况下,值类型的属性不能在它的实例方法中被修改。

如果你确实需要在某个特定的方法中修改结构体或者枚举的属性,你可以为这个方法选择 可变(mutating)行为,然后就可以从其方法内部改变它的属性;并且这个方法做的任何改变都会在方法执行结束时写回到原始结构中。方法还可以给它隐含的 self 属性赋予一个全新的实例,这个新实例在方法结束时会替换现存实例

使用 可变方法,将关键字 mutating 放到方法的 func 关键字之前就可以了

struct Point {
    var x = 0.0, y = 0.0
    mutating func moveBy(x deltaX: Double, y deltaY: Double) {
        x += deltaX
        y += deltaY
    }
}
var somePoint = Point(x: 1.0, y: 1.0)
somePoint.moveBy(x: 2.0, y: 3.0)
print("The point is now at (\(somePoint.x), \(somePoint.y))")
// 打印“The point is now at (3.0, 4.0)”

注意,不能在结构体类型的常量(a constant of structure type)上调用可变方法,因为其属性不能被改变,即使属性是变量属性

let z: Point = 0.0

 mutating func setPointLocation(z :Double) {
        self.z += z //z 为let时。 Left side of mutating operator isn't mutable: 'z' is a 'let' constant
    }

不能在结构体类型的常量(a constant of structure type)上调用可变方法,因为其属性不能被改变,即使属性是变量属性

在可变方法中给 self 赋值

struct Point {
    var x = 0.0, y = 0.0
    mutating func moveBy(x deltaX: Double, y deltaY: Double) {
        self = Point(x: x + deltaX, y: y + deltaY)
    }
}
struct Point {
    var x = 0.0, y = 0.0
    mutating func moveBy(x deltaX: Double, y deltaY: Double) {
        self = Point(x: x + deltaX, y: y + deltaY)
    }
}

枚举的可变方法可以把 self 设置为同一枚举类型中不同的成员:

enum TriStateSwitch {
    case off, low, high
    mutating func next() {
        switch self {
        case .off:
            self = .low
        case .low:
            self = .high
        case .high:
            self = .off
        }
    }
}
var ovenLight = TriStateSwitch.low
ovenLight.next()
// ovenLight 现在等于 .high
ovenLight.next()
// ovenLight 现在等于 .off

类型方法

在方法的 func 关键字之前加上关键字 static,来指定类型方法。类还可以用关键字 class 来指定,从而允许子类重写父类该方法的实现。

在 Objective-C 中,你只能为 Objective-C 的类类型(classes)定义类型方法(type-level methods)。在 Swift 中,你可以为所有的类、结构体和枚举定义类型方法。每一个类型方法都被它所支持的类型显式包含。

class SomeClass {
    class func someTypeMethod() {
        // 在这里实现类型方法
    }
}
SomeClass.someTypeMethod()

特性声明的函数,表明该函数虽然有返回值,但如果没有使用该返回值,编译器不会产生警告。

一个类型方法可以直接通过类型方法的名称调用本类中的其它类型方法,而无需在方法名称前面加上类型名称。类似地,在结构体和枚举中,也能够直接通过类型属性的名称访问本类中的类型属性,而不需要前面加上类型名称

LevelTracker 监测玩家已解锁的最高等级。这个值被存储在类型属性 highestUnlockedLevel 中

struct LevelTracker {
    static var highestUnlockedLevel = 1
    var currentLevel = 1

    static func unlock(_ level: Int) {
        if level > highestUnlockedLevel { highestUnlockedLevel = level }
    }

    static func isUnlocked(_ level: Int) -> Bool {
        return level <= highestUnlockedLevel //或者用 LevelTracker.highestUnlockedLevel
    }

    @discardableResult// 特性声明的函数,表明该函数虽然有返回值,但如果没有使用该返回值,编译器不会产生警告
    mutating func advance(to level: Int) -> Bool {
        if LevelTracker.isUnlocked(level) {
            currentLevel = level
            return true
        } else {
            return false
        }
    }
}

Player 类使用 LevelTracker 来监测和更新每个玩家的发展进度:

class Player {
    var tracker = LevelTracker()
    let playerName: String
    func complete(level: Int) {
        LevelTracker.unlock(level + 1)
        tracker.advance(to: level + 1)
    }
    init(name: String) {
        playerName = name
    }
}

Player 类创建一个新的 LevelTracker 实例来监测这个用户的进度。它提供了 complete(level:) 方法,一旦玩家完成某个指定等级就调用它。这个方法为所有玩家解锁下一等级,并且将当前玩家的进度更新为下一等级。

新的玩家创建一个 Player 的实例

var player = Player(name: "Argyrios")
player.complete(level: 1)
print("highest unlocked level is now \(LevelTracker.highestUnlockedLevel)")
// 打印“highest unlocked level is now 2”

创建了第二个玩家,并尝试让他开始一个没有被任何玩家解锁的等级,那么试图设置玩家当前等级将会失败:

player = Player(name: "Beto")
if player.tracker.advance(to: 6) {
    print("player is now on level 6")
} else {
    print("level 6 has not yet been unlocked")
}
// 打印“level 6 has not yet been unlocked”

总结

1、类、结构体、枚举都可以有自己的实例方法和类型方法

2、实例方法和类型方法分别只能被实例和类型调用

3、用static 修饰func 来声明类型方法。类里还可以class来声明

4、struct和enum里的普通实例方法不可以更改self相关属性。如修改需要用mutating 修饰func

5、类型方法里调用类型属性时可以不用self.类似实例方法里调用属性

学习swift的参考和笔记,感谢 :Swift 编程 Swift51.com

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值