美文网首页
认识Swift系列10之下标(类、结构体、枚举皆可用)

认识Swift系列10之下标(类、结构体、枚举皆可用)

作者: Niuszeng | 来源:发表于2019-07-12 15:41 被阅读0次
        // 下标subscript本质就是一个方法
        // 使用下标定义了方法后,外部可以通过中括号[]方式方位setter和getter方法
        // subscript方法的返回值类型决定了set的newValue类型和get方法的返回值类型
        class Point {
            var x = 0.0, y = 0.0, z = 0.0
            subscript(index: Int) -> Double {
                set {
                    if index == 0 {x = newValue}
                    else if index == 1 {y = newValue}
                    else  {z = newValue}
                }
                get {
                    if index == 0 {return x}
                    else if index == 1 {return y}
                    else  {return z}
                }
            }
            
            subscript(index: String) -> Double {
                set {
                    if index == "x" {x = newValue}
                    else if index == "y" {y = newValue}
                    else  {z = newValue}
                }
                get {
                    if index == "x" {return x}
                    else if index == "y" {return y}
                    else  {return z}
                }
            }
            
            func show() {
                print("x == \(x),y == \(y),z == \(z)")
            }
        }
        
        let p = Point()
        p.show()
        
        p[0] = 20
        p[1] = 1
        p[2] = 9
        p.show()
        
        p["x"] = 33
        p["y"] = 44
        p["z"] = 55
        p.show()
        
        
        // subscript可以没有set方法,但是必须要有get方法,只有get的时候,可以省略get
        // 必须有get,可以省略set
        class Size {
            var w = 0.0, h = 0.0
            // 只有get
            /**
             subscript(index: Int) -> Double {
                 get {
                     if index == 0 {return w}
                     else  {return h}
                 }
             }
             */
            // 只有get可以省略get
            subscript(index: Int) -> Double {
                if index == 0 {return w}
                else  {return h}
            }
            
            func show() {
                print("w == \(w),h == \(h)")
            }
        }
        
        // 可以设置参数标签
        class Point1 {
            var x = 0.0, y = 0.0, z = 0.0
            subscript(indexTag index: Int) -> Double {
                set {
                    if index == 0 {x = newValue}
                    else if index == 1 {y = newValue}
                    else  {z = newValue}
                }
                get {
                    if index == 0 {return x}
                    else if index == 1 {return y}
                    else  {return z}
                }
            }
            func show() {
                print("x == \(x),y == \(y),z == \(z)")
            }
        }
        
        let p1 = Point1()
        p1.show()
        
        p1[indexTag: 0] = 23
        p1[indexTag: 1] = 33
        p1[indexTag: 2] = 43
        p1.show()
        
        // 下标可以传多个参数
        // 下标可以使类方法
        class Point2 {
            static subscript(v1: Int, v2: Int) -> Int {
                v1 + v2
            }
        }
        print(Point2[1, 10])
        
        // 下标返回结构体和类的区别
        // 当结构体类添加下标方法的时候,有适合可能必须加入set方法
        func testStruct() {
            class File {
                var x = 0, y = 0
            }
            class FileManager {
                var f = File()
                subscript(index: Int) ->File { f }
            }
            
            let fm = FileManager();
            fm[0].x = 10
            fm[0].y = 10
            print("class fm f (\(fm.f.x), \(fm.f.y))")
        }
        func testClass() {
            struct File {
                var x = 0, y = 0
            }
            struct FileManager {
                var f = File()
                subscript(index: Int) ->File {
                    set {
                        f = newValue
                        // 虽然外部值修改f的x属性,但实际操作是外部会构建新的结构体来进行值覆盖
                    }
                    get {f}
                }
            }
            
            var fm = FileManager();
            fm[0].x = 10 // f = File(x: 10, y: fm[0].y)
            fm[0].y = 10 // f = File(x: fm[0].x, y: 10)
            // 两句代码虽然是对f成员的x和y赋值,但对于结构体来说实际上是内存中值得copy过程
            // 即 f.x = 10 等价于 f = File(x:10 y:f.y)
            // 因此,fm[0].x = 10实际上需要调用下标方法中的set方法
            // 所以,下标方法必须实现set
            
            print("class fm f (\(fm.f.x), \(fm.f.y))")
        }
        testStruct()
        testClass()
        
        // 接收多个参数的下标
        class Grid {
            static let NotFound = -1
            var data = [
                [0, 1, 2],
                [3, 4, 5],
                [6, 7, 8]
            ]
            
            subscript(row: Int, column: Int)->Int {
                set {
                    guard (row >= 0 && row < 3) && (column >= 0 && column < 3) else { return }
                    data[row][column] = newValue
                }
                get{
                    guard (row >= 0 && row < 3) && (column >= 0 && column < 3) else { return Grid.NotFound }
                    return data[row][column]
                }
            }
        }
        
        var g = Grid()
        g[0, 0] = 40
        g[1, 1] = 40
        g[2, 2] = 40
        print(g.data)
    

    相关文章

      网友评论

          本文标题:认识Swift系列10之下标(类、结构体、枚举皆可用)

          本文链接:https://www.haomeiwen.com/subject/fqfykctx.html