Swift中的多态、初始化、可选链

2021-02-04  本文已影响0人  a_只羊

重写override

    class AnimalSubscript {
        func speak() {
            print("animal speak")
        }
        subscript(index: Int) -> Int {index}
        
        class func eat() {
            print("animal eat")
        }
        
        static func drink() {
            print("animal drink")
        }
    }
    
    class Cat: AnimalSubscript {
        override func speak() {
            print("cat speak")
        }
        
        override subscript(index: Int) -> Int {index + 20}
        override class func eat() {
            print("cat eat")
        }
        
        //此时重写的方法将不能被子类重写修改
//        override static func eat(){
//            print("终结当前的方法")
//        }
        
    }
    class OverrideCircle {
        //懒加载
        lazy var lazyVar: Int = {
            return 1
        }()
        
        private(set) var onlyRead: Int = 0
        var radius: Int = 0
        var diameter: Int{
            get {
                print("get diameter")
                return (radius * 2)
            }
            
            set {
                radius = newValue
                print("Circle set diameter")
            }
        }
        
    }
    
    class OverrideCircleSon: OverrideCircle {
        
        var newRadius = 0
        override var diameter: Int {
            get {
                print("overrideCircleSon get value")
                return radius * 2
            }
            
            set {
                print("overrideCircleSon set value")
                radius = newValue
            }
        }
        
        override var radius: Int{
            get {
                print("reWrite stored perproty of radius")
                return newRadius
            }
            
            set {
                print("reGet sotre perproty of radius")
                newRadius = newValue
            }
        }
    }
    class perprotyObserverClass: OverrideCircle{
        override var radius: Int{
            willSet {
                print("will set value", newValue)
            }
            didSet {
                //此时的radius不会引发死循环,因为此时并没有重写计算属性,此时访问的仍旧是radius本身,
                //属性监听器的实现是通过中间临时变量来实现的,所以不存在死循环
                print("set value finish", oldValue, radius)
            }
        }
        //不能够正常添加观察期监听
//        override var onlyRead: Int{
//            willSet {
//
//            }
//        }
        override var lazyVar: Int{
            willSet {
                print("lazy load will set")
            }
        }
    }
final class finalClass {
        final var radius: Int {
            set {
                print("radius write")
            }
            get {
                print("circle get radius")
                return 20
            }
        }
        
    }

多态

  1. 多态是指:父类指针指向子类对象的行为现象
  2. 在OC中多态是依靠runtime来实现的,而Swift中的实现方式类似于C++中的虚函数表来实现的

几个问题:

  1. 父类是如何判断对应的子类对象的类型的(多态)
  2. 如果将class类型换成struct类型,那么在内存中调用的时候有什么区别?
    因为对于结构体来说,存储在栈空间,所以存储的地址在编译期间就已经确定。而对象的实例,需要堆空间去动态分配内存,此时的堆空间的地址是动态分配的,由此调用对应的方法由于对象实例分配动态的原因,并不能直接在编译期间直接找到其内存地址,所以需要在运行的时候去找到动态分配的地址空间,进而去通过该地址间接找到要调用的方法地址,因此对象的方法的调用地址是变化的。所以相比于类调用方法,结构体调用的方法执行效率要比放在类中执行的效率高很多

初始化器

    class Person {
        var name: String
        init(name: String) {
            self.name = name
        }
    }
    
    class Student: Person {
        
        var score: Int
        var height: Double
        
        //指定初始化器
        init(score: Int, height: Double) {
            self.score = score
            self.height = height
            super.init(name: "student")
        }
        
        //便携初始化器
        convenience init(score: Int) {
            self.init(score:99, height: 20.0)
            self.score = score
        }
        
        //重写父类的指定初始化器为便捷初始化器
        convenience override init(name: String) {
            self.init(score: 98, height: 177)
        }
        
    }
class Animal {
        var type: String {
            didSet {
                print("oldValue:\(oldValue), new value:\(type)")
            }
            willSet {
                print("newValue:\(newValue)")
            }
        }
        
        required init(type: String) {
            self.type = type
        }
    }
    
    class Dog: Animal {
        
        var age: Int
        init(age: Int) {
            self.age = age
            super.init(type: "dog")
        }
        
        required init(type: String) {
            self.age = 0
            super.init(type: "dog")
            self.type = "pig"
        }
        
    }
class PersonCanFailed {
        var name: String
        var age: Int?
        init?(name: String) {
            if name.isEmpty {
                return nil
            }
            self.name = name
        }
        
        //定义一个便捷初始化器
        convenience init?() {
            self.init(name: "leo") //如果初始化失败,后序代码将不会再执行
            self.age = 10
        }
        
        //已经接触到的可失败初始化器
        func demo() {
            //可能初始化失败
            let _ = Int("12345555")
            enum Answer: Int{
                case wrong, right
            }
            //可能初始化失败
            let _ = Answer(rawValue: 1)
        }
    }

    func testOptinolChainUse() {
        var scores = ["Jack": [89, 99, 67],
                      "Rose": [89, 99, 67]]
        
        scores["Jack"]?[0] = 100
        scores["Rose"]?[2] = 87
        
        //判断下面num1与num2 内容是什么类型
        var num1: Int? = 5
        num1? = 10   //Optinoal(10)
        
        //num2? 等同于判定num2是否为空,如果为空后序赋值操作将取消,如果不为空则正常操作
        var num2: Int? = nil
        num2? = 10  //nil
        num2 = 19 //19
    }
    
    func testOptionalChainDictUse() {
        var dict:[String: (Int, Int) -> Int] = ["sum":(+), "difference":(-)]
        var result = dict["sum"]?(10, 20) //Optional(30), Int?
        
    }

可选链 ?

func testOptionlUse() {
        var person: CarPerson? = CarPerson()
        var age = person?.age()  //可选链调用
        var age1 = person!.age() //强制解包
        var name = person?.name  //可选链调用
        var result = person?.eat() //没有返回值仍能够通过变量去接受返回值
        
        if let _ = person?.eat() {
            print("调用eat成功")
        }else{
            print("调用eat失败")
        }
    }
上一篇 下一篇

猜你喜欢

热点阅读