当前位置:   article > 正文

Swift5 9.Methods, 下标Subscripts, 继承Inheritance_swift5.9

swift5.9

Methods

Methods是与特定类型关联的函数。类,结构和enumerations都可以定义实例方法,这些实例方法封装了用于处理给定类型的实例的特定任务和功能。类,结构和枚举也可以定义与类型本身关联的类型方法。

Instance Methods

实例方法是属于特定类,结构或枚举的实例的函数。它们通过提供访问和修改实例属性的方式,或者通过提供与实例目的相关的功能,来支持那些实例的功能。

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

let counter = Counter()
// the initial counter value is 0
counter.increment()
// the counter's value is now 1
counter.increment(by: 5)
// the counter's value is now 6
counter.reset()
// the counter's value is now 0
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

类型的每个实例都有一个称为的隐式属性self,它与实例本身完全等效。

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

struct Point {
    var x = 0.0, y = 0.0
    func isToTheRightOf(x: Double) -> Bool {
        return self.x > x   //用self消除歧义
    }
}
let somePoint = Point(x: 4.0, y: 5.0)
if somePoint.isToTheRightOf(x: 1.0) {
    print("This point is to the right of the line where x == 1.0")
}
// Prints "This point is to the right of the line where x == 1.0"
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

从实例方法中修改值类型 mutating

结构和枚举是值类型。默认情况下,不能从其实例方法中修改值类型的属性。在func前面添加mutating关键字,可以从方法内部更改(即更改)其属性,并在方法结束时将其所做的任何更改写回到原始结构。
下例,Point上面的结构定义了一种变异moveBy(x:y:)方法,该方法将Point实例移动一定量。实际上,此方法不是返回新的点,而是修改了调用它的点。

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))")
// Prints "The point is now at (3.0, 4.0)"

let fixedPoint = Point(x: 3.0, y: 3.0)  // 不能在struct的let上调用Mutating methods
fixedPoint.moveBy(x: 2.0, y: 3.0)
// this will report an error
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

Mutating methods 中分配给self

Mutating methods 可以为隐式self属性分配一个全新的实例。Point上面显示的示例可能是通过以下方式编写的:

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)
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
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 is now equal to .high
ovenLight.next()
// ovenLight is now equal to .off
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

Type Methods

实例方法是您在特定类型的实例上调用的方法,还可以定义在类型本身上调用的方法。

class SomeClass {
    class func someTypeMethod() {
        // type method implementation goes here
    }
}
SomeClass.someTypeMethod()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

在类型方法主体内使用的任何不合格的方法和属性名称都将引用其他类型级别的方法和属性。一个类型方法可以使用另一个方法的名称来调用另一个类型方法,而无需在其前面加上类型名称。同样,结构和枚举上的类型方法可以使用类型属性的名称访问类型属性,而无需使用类型名称前缀。

这里有一个例子struct LevelTracker {}可跟踪玩家在游戏的不同级别或阶段的进度,暂不放入。

下标Subscript

Classes, structures, enumerations都可以定义Subscript,这些下标是用于访问集合,列表或序列的成员元素的快捷方式。subscripts可以是读写的也可以是只读的,应get{}和set{}实现

subscript(index: Int) -> Int {
    get {
        // Return an appropriate subscript value here.
    }
    set(newValue) {
        // Perform a suitable setting action here.
    }
}

// 只读,省略get{}
subscript(index: Int) -> Int {
    // Return an appropriate subscript value here.
}

struct TimesTable {
    let multiplier: Int
    subscript(index: Int) -> Int {
        return multiplier * index
    }
}
let threeTimesTable = TimesTable(multiplier: 3)
print("six times three is \(threeTimesTable[6])")
// Prints "six times three is 18"
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

下标用法

下标通常用作访问集合,列表或序列中的成员元素的快捷方式。Dictionary类型实现了下标来设置和检索Dictionary实例中存储的值,键值下标接受并返回type Int?或“ optional int”的值

var numberOfLegs = ["spider": 8, "ant": 6, "cat": 4]
numberOfLegs["bird"] = 2
  • 1
  • 2

下标可以采用任意数量的输入参数,并且这些输入参数可以是任何类型。下标还可以返回任何类型的值。与function不同,下标不能使用输入输出参数。

struct Matrix {
    let rows: Int, columns: Int
    var grid: [Double]
    init(rows: Int, columns: Int) {
        self.rows = rows
        self.columns = columns
        grid = Array(repeating: 0.0, count: rows * columns)
    }
    func indexIsValid(row: Int, column: Int) -> Bool {
        return row >= 0 && row < rows && column >= 0 && column < columns
    }
    subscript(row: Int, column: Int) -> Double {
        get {
            assert(indexIsValid(row: row, column: column), "Index out of range")
            return grid[(row * columns) + column]
        }
        set {
            assert(indexIsValid(row: row, column: column), "Index out of range")
            grid[(row * columns) + column] = newValue
        }
    }
}

var matrix = Matrix(rows: 2, columns: 2)

matrix[0, 1] = 1.5
matrix[1, 0] = 3.2

let someValue = matrix[2, 2]
// This triggers an assert, because [2, 2] is outside of the matrix bounds.
  • 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

上面的示例创建一个Matrix具有两行两列的新实例。该实例的grid数组Matrix实际上是矩阵的展平版本,从左上角到右下角读取:
在这里插入图片描述
在这里插入图片描述

Type Subscripts

如上所述,实例下标是您在特定类型的实例上调用的下标。您还可以定义在类型本身上调用的下标。这种下标称为类型下标。可以subscript关键字之前写入关键字static。

enum Planet: Int {
    case mercury = 1, venus, earth, mars, jupiter, saturn, uranus, neptune
    static subscript(n: Int) -> Planet {
        return Planet(rawValue: n)!
    }
}
let mars = Planet[4]
print(mars)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

继承Inheritance

一个类可以从另一个类继承方法,属性和其他特征。当一个类从另一个类继承时,继承的类称为子类,而其继承的类称为其超类。

基类Base Class

任何不从其他类继承的类都称为基类。

class Vehicle {
    var currentSpeed = 0.0
    var description: String {
        return "traveling at \(currentSpeed) miles per hour"
    }
    func makeNoise() {
        // do nothing - an arbitrary vehicle doesn't necessarily make a noise
    }
}

let someVehicle = Vehicle()

print("Vehicle: \(someVehicle.description)")
// Vehicle: traveling at 0.0 miles per hour
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

子类Subclass

子类化是在现有类的基础上建立新类的行为。子类继承现有类的特征,然后可以对其进行优化。还可以向子类添加新特征。

class SomeSubclass: SomeSuperclass {  // 在超类名称之前写上子类名称
    // subclass definition goes here
}
  • 1
  • 2
  • 3
class Bicycle: Vehicle {
    var hasBasket = false // Bicycle类定义的新属性
}
bicycle.currentSpeed = 15.0  // 修改属性
print("Bicycle: \(bicycle.description)")
// Bicycle: traveling at 15.0 miles per hour


class Tandem: Bicycle {  // 子类本省还可以继续子类化
    var currentNumberOfPassengers = 0
}let tandem = Tandem()
tandem.hasBasket = true
tandem.currentNumberOfPassengers = 2
tandem.currentSpeed = 22.0
print("Tandem: \(tandem.description)")
// Tandem: traveling at 22.0 miles per hour
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

Overriding

子类可以提供其自己的实例方法,类型方法,实例属性,类型属性或下标的自定义实现,否则该实例方法将从超类继承。这称为覆盖。要覆盖原本会被继承的特征,在覆盖定义的前面加上override关键字。

class Train: Vehicle {
    override func makeNoise() {
        print("Choo Choo")
    }
}

let train = Train()
train.makeNoise()
// Prints "Choo Choo"
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

通过在子类属性重写中同时提供getter和setter,可以将继承的只读属性呈现为读写属性。但不能将继承的读写属性表示为只读属性,如果在属性替代中提供了一个setter,则还必须为该替代提供一个getter。

Overriding Property Observers

您可以使用属性覆盖将属性观察器添加到继承的属性。这使您可以在继承属性的值更改时得到通知。
不能将属性观察器添加到继承的常量存储属性或继承的只读计算属性。这些属性的值无法设置,因此不建议提供willSet或didSet实现作为替代的一部分。

class AutomaticCar: Car {
    override var currentSpeed: Double {
        didSet {
            gear = Int(currentSpeed / 10.0) + 1
        }
    }
}

let automatic = AutomaticCar()
automatic.currentSpeed = 35.0
print("AutomaticCar: \(automatic.description)")
// AutomaticCar: traveling at 35.0 miles per hour in gear 4
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

防止被Override

可以通过将方法,属性或下标标记为final来防止其被覆盖,如final var, final func, final class func, final subscript

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/223690
推荐阅读
相关标签
  

闽ICP备14008679号