从零开始的SWIFT开发记录之属性 (下)

202 阅读3分钟

mutating 关键字

在结构体(值类型,枚举也适用)中,如果要修改自身的成员变量,不能直接修改,要加上mutating,或者不用结构体,直接用类。

struct Value{

    var x = 0

    var y = 0

    

    mutating func change(x1:Int,y1:Int){

        x = x + x1

        y = y + y1

    } 

}

@discardableResult

Result of call to 'change(x1:y1:)' is unused 警告是说返回值可能没有使用,可以在方法之前加@discardableResult,表示返回值可使用也可以不使用,只是调用不会报警告,个人建议还是少用比较好,方法的目的性要明确,不然可能会误解。


**class** CountValue:NSObject{

    

    **var** x = 0

    **var** y = 0

    

   **@discardableResult** **func** change(x1:Int,y1:Int) -> Int{

        x = x + x1

        y = y + y1

        

        **return** x

    }

}

        let p = CountValue()

        p.change(x1: 1, y1: 2)

subscript

subscript可以给任意类型添加下标,本质是方法,类似于数组使用,必须有get方法,可以没有set方法


**subscript**(index:Int)->Int{

            **set**{

                **if** index == 0{

                    **self**.x = newValue

                }

                **if** index == 1{

                    **self**.y = newValue

                }

            }

            **get**{

                **if** index == 0 {

                    **return** **self**.x

                }

                **if** index == 1 {

                    **return** **self**.y

                }

                **return** 0

            }

        }
        
        
        **let** p = Point(x: 0, y: 0)

        p[0] = 10

        p[1] = 11

        print(p.x,p.y)  // 10 11
        

也可以为下标添加多个值,默认是实例方法



        class PlueMethod {

        static subscript (a:Int,b:Int)->Int{

            return a + b

        }

    }
    
    print(PlueMethod[10,20]) // 30
    

继承

值类型不支持继承,只有类才有继承。

swift不像oc每个类都有最终继承类,只要没有父类都是基类。

子类可以重写父类的下标,属性,方法。

子类继承父类,默认会获得父类的属性,会把父类的属性放到前面,内存会增加

重写实例方法,只需要在也是一定要在方法前面加上override

重写类型方法,只有被class修饰的类型方法可以被子类重写,被static修饰的不行。

重写属性,只能重写成计算属性,不能重写成实例属性

只能重写var属性,不能重写let属性

子类重写父类,权限不能比父类小,父类可读可写,子类必须可读写,父类可读,子类可读也可以可读写。

如果是类型属性,只有计算类型属性可以被子类重写,存储类型属性不能被class修饰。

重写实例属性

**class** subCircle:CirCle{

        

        **override** **var** radio: Double {

            

            **set**{

                **super**.radio = newValue

            }

            **get**{

                print("get radio")

                **return** **super**.radio

            }

        }

        

        **override** **var** diameter: Double{

            **set**{

                print("set diameter")

                **super**.diameter = newValue

            }

            **get**{

                print("get diameter")

                **return** **super**.diameter

            }

        }

    }

注意,这里都是通过获取父类里的属性来修改的,如果不加super,默认就是self,如果改成self,会导致死循环,不断调用本类的set或者get方法。

属性观察器

可以为父类添加属性观察器,只读和let修饰的不能添加属性观察器,如果不想被子类继承,可以添加关键字final

父类没有属性观察器

截屏2022-06-21 17.29.15.png

父类有属性观察器

给子类设置一个值,调用顺序是子类的willget,父类的willget,父类的didiset,子类的didiset。

swift中多态的实现原理

通过对象地址找到这个对象所在堆空间的首地址,然后通过首地址找到关于这个类的类型信息,在类的类型信息中包含了方法的地址,然后通过固定偏移量找到这个方法地址。在程序编译完成以后,方法的地址就已经确定了,知道类要调用的方法是谁。