Swift 继承、初始化器⑨

2020-08-04  本文已影响0人  Aliv丶Zz

⑫⑬⑪⑭⑮

1. 继承的简单介绍


1.1 重写实例方法、下标

class Animal {
    func speak() {
        print("Animal Speak")
    }
    subscript(index: Int)-> Int{
        get{
            return index
        }
    }
}

class Dog: Animal {
    override func speak() {
        super.speak()
        print("Dog Speak")
    }
    override subscript(index: Int) -> Int {
        get{
            return super[index] + 1
        }
    }
}

class ErHa: Dog {
    var iq = 0
}
var ani = Animal()
var d = Dog()

ani.speak()
print("Ani:",ani[1])
print("================")
d.speak()
print("Dog:",d[1])
print("================")

打印结果:

Animal Speak
Ani: 1
================
Animal Speak
Dog Speak
Dog: 2
================

注意:


1.2 重写实例属性

实例:

class Circle {
    var radius: Int = 0
    var diameter: Int{
        set{
            print("Circle setDiameter")
            radius = newValue / 2
        }
        get{
            print("Circle getDiameter")
           return radius * 2
        }
    }
}

class SubSircle: Circle {
    override var radius: Int {
        set{
            print("SubSircle setRadius")
            super.radius = newValue > 0 ? newValue : 0
        }
        get{
            print("SubSircle setRadius")
            return super.radius
        }
    }
    override var diameter: Int {
        set{
            print("SubSircle setDiameter")
            super.diameter = newValue > 0 ? newValue : 0
            
        }
        get{
            print("SubSircle getDiameter")
            return super.diameter
        }
    }
    
}
var circle = SubSircle()

circle.radius = 9
print("=======")
print(circle.diameter)
print("=======")
circle.diameter = 20
print("=======")
print(circle.radius)

【打印结果】

SubSircle setRadius
=======
SubSircle getDiameter
Circle getDiameter
SubSircle setRadius
18
=======
SubSircle setDiameter
Circle setDiameter
SubSircle setRadius
=======
SubSircle setRadius
10


1.2 重写类型属性


2. 属性观察器


3. 初始化器

//指定初始化
class Person {
    var name: String = ""
    var age: Int = 0
    init(name: String, age: Int) {
        self.name = name
        self.age = age
    }
}

//便捷初始化
class Student {
    var name: String = ""
    var age: Int = 0
     convenience init(name: String, age: Int){
          self.init()
          self.name = name
          self.age = age
      }
}
var p = Person(name: "Jack", age: 18)
var s = Student()
var s2 = Student(name: "Jack", age: 18)

注意: 如果重新写了指定初始化器。则init()不再自动生成


3.1 初始化器的相互调用规则
  • 指定初始化器必须从他的直系父类调用指定初始化器
  • 便捷初始化器必须从相同的类里调用另一个初始化器
  • 便捷初始化器最终必须调用一个指定初始化器
3.2 两段式初始化

  Swift在变成方面为了保证初始化过程中的安全,设定了两段式初始化安全检查

第一阶段:初始化所有存储属性

  • 外层调用指定、便捷初始化器
  • 分配内存给实例,但未初始化
  • 指定初始化器确保当前类定义的存储属性都初始化
  • 指定初始化器调用父类的初始化器,不断向上调用,形成初始化器链

第二阶段:设置新的存储属性

  • 从顶部初始化器往下,链中的每一个指定初始化器都有机会进一步制定实例
  • 从初始化器现在能够使用self(访问、修改它的属性,调用它的实例方法等等)
  • 最终,链中任何便捷初始化器都有机会定制实例以及使用self
3.3 安全检查
  • 指定初始化器必须保证在调用父类初始化器之前,其所在类定义的所有存储属性都要初始化完成
  • 指定初始化器必须先调用父类初始化器,然后才能为集成的属性设置新值
  • 便捷初始化器必须先调用同类中的其他初始化器,然后再为任意属性设置新值
  • 初始化器在第1阶段初始化完成之前,不能调用任何实例方法、不能读取任何实例属性的值,也不能引用self
  • 知道第一阶段结束,实例才算完全合法
3.4 初始化器的重写
  • 当重写父类的指定初始化器时,必须加上 override (即使子类的实现是便捷式初始化器)
  • 如果子类写了一个匹配父类便捷初始化器的初始化器,不用加上override
  • 因为父类的便捷初始化器永远不会通过子类直接调用,因此,严格来说,子类无法重写父类的便捷初始化器

3.3 自动继承
  • 1 如果子类没有定义任何指定初始化器,他们会自动继承父类所有的指定初始化器
  • 2 如果子类提供了父类所有指定初始化器的实现(要么通过方式1继承,要么重写),子类会自动继承所有的父类便捷初始化器
  • 3 就算子类添加了更多的便捷初始化器,这些规则仍然适用
  • 4 子类以便捷初始化器的形式重写父类的指定初始化器,也可以作为满足规则②的一部分

4. required关键字

class Person {
    required init(){
        
    }
    init(age: Int) {
        
    }
}

class Student: Person {
    required init() {
        super.init()
    }
   
}

4. 可失败初始化器

//非可失败 调用 可失败初始化器
class Person {
   var name: String
   var age: Int
   init?(name:String) {
       if name.isEmpty {
           return nil
       }else{
           self.name = name
       }
       self.age = 18
   }
   
   convenience init() {
       self.init(name:"Jack")!//
   }
}
var p = Person()
print(p)



//可失败 调用 非可失败初始化器
class Person {
   var name: String
   var age: Int
  convenience init?(name:String) {
       self.init()
       if name.isEmpty {
           return nil
       }
   }
   
    init() {
       self.name = "jack"
       self.age = 10
   }
}


var p = Person(name: "")
print(p)
var p2 = Person(name: "Jack")
print(p2)

5. 反初始化器

deinit叫做反初始化器,类似于C++的析构函数、OC中的dealloc

class Animal {
    deinit {
        print("Animal deinit")
    }
}

class Dog:Animal {
    deinit {
        print("Dog deInit")
    }
}

var dog:Dog? = Dog()
dog = nil

【打印结果】:

Dog deInit
Animal deinit

6. 可选链

class Car { var price = 100000 }
class Dog { var weight = 0 }

class Person {
    var name: String = ""
    var dog: Dog = Dog()
    var car: Car? = Car()
    func age() -> Int {
       return 18
    }
    func eat() {
        print("Person eat")
    }
    subscript(index: Int) -> Int{
        return index
    }
    
}
var person:Person? = Person()

var age1 = person!.age()// Int
var age2 = person?.age()// Int?
var index = person?[6]//Int?

if let age = person?.age(){
    print(age)
}else{
    print("age() 调用失败")
}
func getName() -> String {
    return "Jack"
}
person?.name = getName()

注意: 如果person为nil,则不会调用getName()

ar num1: Int? = 5
num1? = 10//Optional(10)
var num2: Int? = nil
num2? = 10//nil

print(num1,num2)
var dict:[String:(Int, Int) -> Int] = [
    "sum" : (+),
    "diff":(-)
]
var result = dict["sum"]?(10,20)//Optional(30)
上一篇 下一篇

猜你喜欢

热点阅读