swift5.x 类、结构体、枚举

时间:2020-05-25
本文章向大家介绍swift5.x 类、结构体、枚举,主要包括swift5.x 类、结构体、枚举使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
//
//  ViewController7.swift
//  swiftT
//
//  Created by wjwdive on 2020/5/20.
//  Copyright © 2020 wjwdive. All rights reserved.
//

import UIKit

class ViewController7: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        
        // swift里 类,枚举,结构体 三者基本具有同等的地位(三者都可以定义属性,方法,下标,构造体,嵌套类型)
        
        //枚举和结构体是值类型, 类是引用类型
        
        // 类和结构体的不同
        // 继承允许一个类继承另一个类的特征
        // 类型转换允许你在运行检查和解释一个类实例的类型
        // 反初始化器允许一个实例释放任何其所被分配的资源
        // 引用计数器允许不止一个对类实例的引用
        
        
        //增强的枚举
        // 用enum 关键字类定义一个枚举,让后将其所有的定义内容放在一个大括号中
        // 多个成员值可以出现在同一行中,要用逗号隔开
        enum CompassPoint {
            case east
            case weast
            case sourth
            case north
        }
        
        
        
        //每一个枚举都定义了一个全新的类型,正如 Swift 中其它的类型那样,它们的名称需要【首字母大写】。给枚举起一个单数的而不是复数的名字,从而使得它们能够顾名思义
        enum Planet {
            case mercury, venus, earth, mars, jupiter, saturn, uranus, neptune
        }
        
        
        
        //延迟存储属性
        // 延迟存储属性的初始值在其第一次使用时才进行计算。你可以通过在其声明前标柱lazy修饰语来表示一个延迟存储属性
        // 如果被标记为 lazy 修饰符的属性同时被多个线程访问并且属性还没有被初始化,则无法保证属性只初始化移除
        class DataImporter {
            var fileName = "data.txt"
            init() {
                print("dataInporter init")
            }
        }
        
        class DataManager {
            lazy var importer = DataImporter()
            var data = [String]()
        }
        
        let manager = DataManager()
        manager.data.append("Some Data")
        manager.data.append("more data")
        print("manager.data.append finish")
        print(manager.importer.fileName)
        
        // 计算属性
        // 除了存储属性,类,结构体和枚举也能够定义计算属性,而它实际并不存储值。相反,它提供了一个读取器和一个可选的设置器来间接得到和其它的属性和值
        
        // 简写 setter: 如果一个计算属性的设置器没有为将要被设置的值定义一个名字,那么它将被默认命名为newValue
        // 简写 getter: 如果整个getter的函数体是一个单一的表达式,那么getter隐式返回这个表达式
        
        
        //只读计算属性
        //一个读取器但是没有设置器的计算属性就是所谓的只读计算属性,只读计算属性返回一个值,也可以通过点语法访问。但是不能被修改为另一个值
        //必须使用var关键字定义计算属性,(包括只读计算属性),因为它们的值不是固定的。let关键字只能用于常量属性,用于明确哪些值一旦作为实例初始化就不能更改。
        struct Point {
            var x = 0.0, y = 0.0
        }
        struct Size {
            var width = 0.0, height = 0.0
        }
        struct Rect {
            var origin = Point()
            var size = Size()
            var center: Point {
                get {
                    let centerX = origin.x + (size.width / 2)
                    let centerY = origin.y + (size.height / 2)
                    return Point(x: centerX, y: centerY)
                    //里面是 一个单一表达式时,可以只写表达式
                    //Point(x: origin.x + (size.width / 2), y: origin.y + (size.height / 2))
                }
                set(newCenter) {// 没有newCenter 默认可以使用newValue
                    origin.x = newCenter.x - (size.width / 2)
                    origin.y = newCenter.y - (size.height / 2)
                }
            }
        }
        
        
        // 属性观察者
        // willSet 会在该值被存储之前被调用
        // didSet 会在一个新值被存储后被调用
        // 如果你实现了一个willSet 观察者,新的属性值会以常量形式参数传递。你可以在你的willSet 实现中为这个参数定义名字。如果你没有为它命名,那么它使用默认的名字 newValue
        // 如果你实现了一个didSet 观察者,一个包含旧属性的常量形式参数会被传递。你可以为它命名,也可以使用默认的形式参数名 oldValue.如果你在属性子集的didSet观察者里给自己赋值,你赋值的新值就会被取代刚刚设置的值。
        
        class StepCounter {
            var totalSteps: Int = 0 {
                willSet(newTotalSteps) {
                    print("About to set totalSteps to \(newTotalSteps)")
                }
                didSet {
                    if totalSteps > oldValue {
                        print("Added \(totalSteps - oldValue) steps")
                    }
                }
            }
        }
        
        let setpCounter = StepCounter()
        setpCounter.totalSteps = 200
        setpCounter.totalSteps = 100
        
        
        // 全局变量,局部变量
        // 观察属性的能力同样对全局变量和局部变量有效。全局变量时定义在任何函数、方法、闭包或者类型环境之外的变量。局部变量时定义在函数、方法、或者闭包环境之中的变量
        
        //类型属性【新】
        // 使用static关键字来定义类型属性,对于类型属性的计算类型属性,可以使用class关键字来允许子类充血父类的实现
        class SomeClass {
            static var storedTypeProperty = "some value"
            static var computedTypeProperty: Int {
                return 27
            }
            class var overrideableComputedTypeProperty: Int {
                return 100
            }
        }
        
        
        
        var apoint = PointS(x: 2, y: 2)
        apoint.printPoint()//调用实例方法
        PointS.printTypeInfo()//调用类方法(静态方法)
        
        let threeTimesTable = TimesTable(mutiplier: 3)
        print("six times three is \(threeTimesTable[6])")
        
        //下标示例
        var matrix = Matrix(rows: 2, columns: 2)
        matrix[0, 0] = 1
        matrix[1, 1] = 1
        print(matrix)
        
        // 类型下标示例 Xcode 11 swift5.x
        print("类型下标示例 " ,PlanetA[3])
    }
    

    /*
    // MARK: - Navigation

    // In a storyboard-based application, you will often want to do a little preparation before navigation
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        // Get the new view controller using segue.destination.
        // Pass the selected object to the new view controller.
    }
    */

}

struct PointS {
    var x = 0
    var y = 0
    func printPoint() {
        print("x is \(x), y is \(y)")
    }
    //静态方法,类方法
    static func printTypeInfo() {
        print("A point")
    }
    //异变方法
    mutating func moveBy(x: Int, y: Int) {
        self.x += x
        self.y += y
        // 或者
        //self = PointS(x: self.x + x, y: self.y + y)
    }
}

// 类,枚举,结构体 可以定义下标,它可以作为访问集合,列表或序列成员元素的快捷方式。你可使用下表索引值来设置或检索值而不需要为设置和检索分别使用实例方法
// 你可以为一个类型定义多个下表,并且下标会基于传入的索引值的类型选择合适的下标重载使用。下标没有限制单个维度,你可以使用多个输入形参来定义下标满足定义类型的需求

//下标语法
//下标脚本允许你通过在实例名后面的方括号内写一个或多个值对该类的实例进行查询。它的语法类似于实例方法和计算属性。使用关键字subscript来定义下标,并且制定一个或多个输入形式参数和返回类型,与实例方法一样。与实例方法不同的是,下标可以是读写的,也可以是只读的
struct TimesTable {
    let mutiplier: Int
    subscript(index: Int) -> Int {
        return mutiplier * index
    }
}


// 下标参数的使用规定
// 下标可以接收任意的输入形式参数,并且这些输入形式参数可以是任意类型。下标可以返回任意类型,下标可以使用变量形式参数和可变形式参数,但是不能使用输入输出形式参数或者提供默认形式参数
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
        }
    }
}

// 类型下标
// 实例下标,你可以在类型的实例上调用下标,你同样也可以定义类型本身的下标。这类下标叫类型下标,你可以通过在subscript 关键字前面加static关键字来标记类型下标。在类里使用class关键字,这样可以允许子类重写父类的下标实现。
enum PlanetA: Int {
    case mercury = 1, venus, earth, mars, jupiter, saturn, uranus, neptune
    static subscript(n: Int) -> PlanetA {
        return PlanetA(rawValue: n)!
    }
}




原文地址:https://www.cnblogs.com/wjw-blog/p/12938584.html