iOS开发之Swift篇(10)—— 方法

版本

Xcode 11.3.1
Swift 5.1.3

方法

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

  • 在 Objective-C 中,类是唯一能定义方法的类型。
  • 在 Swift 中,可在类型(类/结构体/枚举)上定义方法。

实例方法

实例方法是属于某个特定类、结构体或者枚举类型实例的方法。
实例方法有以下特点:

  • 可以访问和修改实例属性
  • 可以访问其所属类型的其他实例方法
  • 要写在它所属的类型的前后大括号({})之间
  • 只能被它所属的类的某个特定实例调用
class Counter {
    
    
    
    var count = 0
    
    func increment() {
    
    
        count += 1
        printSelf()
    }
    
    func increment(by amount: Int) {
    
    
        count += amount
        printSelf()
    }
    
    func reset() {
    
    
        count = 0
        printSelf()
    }
    
    func printSelf() {
    
    
        print("count = \(count)")
    }
}

let counter = Counter()
counter.increment()
counter.increment(by: 2)
counter.reset()

/**
 count = 1
 count = 3
 count = 0
 */

以上示例中, 访问属性/方法都使用了隐式调用.

self 属性

类型的每一个实例都有一个隐含属性叫做self, self 完全等同于该实例本身. 你可以在一个实例的实例方法中使用这个隐含的 self 属性来引用当前实例.
之所以说上面示例中为隐式调用, 是因为其使用了隐含的self属性.
完整写法 (显式调用) 为:

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

虽然我们可以简略self, 但是在某些情况下我们还是需要使用显式写法.
例如, 以上示例中, 把方法 increment(by amount: Int) 中 amount 改成 count, 那么结果就不是我们想要的. 因为参数count优先级大于存储属性count, 而我们希望的是对存储属性count进行计算.
那么就需要使用self, 其效果是一致的:

func increment(by count: Int) {
    
    
        self.count += count
        printSelf()
}

外部参数名称和局部参数名称

在之前的函数章节中, 我们有讨论过参数标签和参数名称.
在本章节中, 因为涉及方法的调用, 我们将参数标签改称为外部参数名称, 将参数名称改为局部参数名称.
Swift 函数参数可以同时有一个局部名称(在函数体内部使用)和一个外部名称(在调用函数时使用)。
像在 Objective-C 中一样,Swift 中方法的名称通常用一个介词指向方法的第一个参数,比如:with,for,by等等。

在第一个示例中, by 为外部参数名称, amount 为局部参数名称

func increment(by amount: Int) {
    
    
        count += amount
        printSelf()
}

counter.increment(by: 2)

我们也可以使用下划线"_"来取代外部参数名称, 这样在调用方法时就没有了外部参数名称 (参数标签) :

func increment(_ count: Int) {
    
    
        self.count += count
        printSelf()
}

counter.increment(2)

在实例方法中修改值类型

Swift 语言中结构体和枚举是值类型。一般情况下,值类型的属性不能在它的实例方法中被修改。
例如:

struct Size {
    
    
    
    var width = 10
    var height = 20

    // 以下方法报错
    func increment(by amount: Int) {
    
    
        width += amount;
        height += amount;
    }
}

但是,如果你确实需要在某个具体的方法中修改结构体或者枚举的属性,你可以选择变异(mutating)这个方法,然后方法就可以从方法内部改变它的属性;方法还可以给它隐含的 self 属性赋予一个全新的实例,这个新实例在方法结束时会替换现存实例。
例如:

struct Size {
    
    
    
    var width = 10
    var height = 20
    
    mutating func increment(by amount: Int) {
    
    
        width += amount;
        height += amount;
    }
}

var size = Size()
print("\(size)")
// Size(width: 10, height: 20)

size.increment(by: 5)
print("\(size)")
// Size(width: 15, height: 25)

在可变方法中给 self 赋值

上面示例中, 可以改写成如下, 得到的结果是一样的:

struct Size {
    
    
    
    var width = 10
    var height = 20
    
    mutating func increment(by amount: Int) {
    
    
//        width += amount;
//        height += amount;
        self = Size(width: width+amount, height: height+amount)
    }
}

枚举的可变方法可以把 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来允许子类重写父类的实现方法。

class Math {
    
    
    class func abs(number: Int) -> Int {
    
    
        if number < 0 {
    
    
            return (-number)
        }else {
    
    
            return number
        }
    }
}

struct Sample {
    
    
    static func abs(number: Int) -> Int {
    
    
        if number < 0 {
    
    
            return (-number)
        }else {
    
    
            return number
        }
    }
}

let number1 = Math.abs(number: -5)
let number2 = Sample.abs(number: -10)

print(number1)
print(number2)
/**
 5
 10
 */

猜你喜欢

转载自blog.csdn.net/u012078168/article/details/104494695