diff --git a/13 继承.playground/Resources/README.md b/13 继承.playground/Resources/README.md index 781188a..8d7c433 100644 --- a/13 继承.playground/Resources/README.md +++ b/13 继承.playground/Resources/README.md @@ -222,4 +222,9 @@ circle.radius = 10 被 `final` 修饰的方法、下标、属性,禁止被重写 -被 `final` 修饰的类,禁止被继承 \ No newline at end of file +被 `final` 修饰的类,禁止被继承 + +#### 多态 + +父类引用指向子类对象 + diff --git a/13 继承.playground/playground.xcworkspace/xcuserdata/jiulinxiri.xcuserdatad/UserInterfaceState.xcuserstate b/13 继承.playground/playground.xcworkspace/xcuserdata/jiulinxiri.xcuserdatad/UserInterfaceState.xcuserstate index 4fca964..a645b8a 100644 Binary files a/13 继承.playground/playground.xcworkspace/xcuserdata/jiulinxiri.xcuserdatad/UserInterfaceState.xcuserstate and b/13 继承.playground/playground.xcworkspace/xcuserdata/jiulinxiri.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/14 初始化.playground/Contents.swift b/14 初始化.playground/Contents.swift new file mode 100644 index 0000000..25c2898 --- /dev/null +++ b/14 初始化.playground/Contents.swift @@ -0,0 +1,104 @@ +import UIKit + +// 类的属性有初始值的时候,默认会有一个 init() 的初始化器 +//class Size { +// var width: Int = 0 +// var height: Int = 0 +//} + +// 等价于 +//class Size { +// var width: Int +// var height: Int +// +// init() { +// width = 0 +// height = 0 +// } +//} + + +class Size { + var width: Int = 0 + var height: Int = 0 + + // 指定初始化器(主要初始化器) + // 用户指定完初始化器之后,会覆盖掉原来的 init()初始化器 + init(width: Int, height: Int) { + self.width = width + self.height = height + } + + // 便捷初始化器 + convenience init(width: Int) { + self.init(width: width, height: 0) + } +} + +var s1 = Size(width: 10, height: 20) +var s2 = Size(width: 30) + + +class Person { + var age: Int + // 指定初始化器 + init(age: Int) { + self.age = age + } + // 便捷初始化器 + convenience init() { + self.init(age: 0) + } +} + +class Student: Person { + var score: Int + // 指定初始化器调用直系父类的初始化器 + init(age: Int, score: Int) { + self.score = score + // super.init 方法放到最后 + super.init(age: age) + } + + // 便捷初始化器调用便捷初始化器 + convenience init() { + self.init(score: 0) + } + + // 便捷初始化器调用指定初始化器 + convenience init(score: Int) { + self.init(age: 0, score: score) + } +} + + +class Animal { + var legs: Int + var name: String + var age: Int + + init(name: String, age: Int, legs: Int) { + self.legs = legs + self.age = age + self.name = name + } + + init(name: String, age: Int) { + self.legs = 4 + self.age = age + self.name = name + } + + convenience init(name: String) { + self.init(name: name, age: 1, legs: 4) + } +} + +class Cat: Animal { + +} + +var cat = Cat(name: "淘气", age: 3, legs: 4) +var cat1 = Cat(name: "淘气", age: 3) +var cat2 = Cat(name: "淘气") + diff --git a/14 初始化.playground/Resources/README.md b/14 初始化.playground/Resources/README.md new file mode 100644 index 0000000..d2b403b --- /dev/null +++ b/14 初始化.playground/Resources/README.md @@ -0,0 +1,175 @@ +--- +gitea: none +include_toc: true +--- + +### 初始化器 + +类、结构体、枚举都可以定义初始化器。类的两种初始化器如下所示 + +* 指定初始化器(designated initializer) +* 便捷初始化器(convenience initializer): 便捷初始化器的前边有 `convenience` 关键字,只能进行当前类横向调用。 + +```swift +// 类的属性有初始值的时候,默认会有一个 init() 的初始化器 +class Size { + var width: Int = 0 + var height: Int = 0 +} + +// 等价于 +class Size { + var width: Int + var height: Int + // 指定初始化器 + init() { + width = 0 + height = 0 + } +} + +class Size { + var width: Int = 0 + var height: Int = 0 + + // 指定初始化器(主要初始化器) + // 用户指定完初始化器之后,会覆盖掉原来的 init()初始化器 + init(width: Int, height: Int) { + self.width = width + self.height = height + } + + // 便捷初始化器 + convenience init(width: Int) { + self.init(width: width, height: 0) + } +} +var s1 = Size(width: 10, height: 20) +var s2 = Size(width: 30) +``` + +#### 类初始化器 + +1. 每个类至少有一个指定初始化器,指定初始化器是类的主要初始化器 +2. 默认初始化器总是类的指定初始化器 +3. 类偏向于少量指定初始化器,一个类通常只有一个指定初始化器 + + + +#### 初始化器的相互调用 + +1. 指定初始化器必须从它的直系父类调用指定初始化器 +2. 便捷初始化器必须从相同的类里调用另一个初始化器 +3. 便捷初始化器最终必须调用一个指定初始化器 + +```swift +class Person { + var age: Int + // 指定初始化器 + init(age: Int) { + self.age = age + } + // 便捷初始化器 + convenience init() { + self.init(age: 0) + } +} + +class Student: Person { + var score: Int + // 指定初始化器调用直系父类的初始化器 + init(age: Int, score: Int) { + self.score = score + // super.init 方法放到最后 + super.init(age: age) + // 个性化定制代码 + ... + } + + // 便捷初始化器调用便捷初始化器 + convenience init() { + self.init(score: 0) + } + + // 便捷初始化器调用指定初始化器 + convenience init(score: Int) { + self.init(age: 0, score: score) + } +} +``` + +初始化器的调用规则如下图所示 + +image-20220113091257659 + + + +#### 两段式初始化 + +第1阶段:初始化所有存储属性 + +* 外层调用指定\便捷初始化器 +* 分配内存给实例,但未初始化 +* 指定初始化器确保当前类定义的存储属性都初始化 +* 指定初始化器调用父类的初始化器,不断向上调用,形成初始化器链 + +第2阶段:设置新的存储属性值 + +* 从顶部初始化器往下,链中的每一个指定初始化器都有机会进一步定制实例 +* 初始化器现在能够使用self(访问、修改它的属性,调用它的实例方法等等) +* 最终,链中任何便捷初始化器都有机会定制实例以及使用self + + + +#### 重写 + +初始化器的重写,即子类重写父类的初始化器方法。 + +* 当重写父类的指定初始化器时,必须加上 `override`(即使子类的实现是便捷初始化器) +* 如果子类写了一个匹配父类便捷初始化器的初始化器,不用加上 `override` + * 因为父类的便捷初始化器永远不会通过子类直接调用 + +#### 自动继承 + +①如果子类没有自定义任何指定初始化器,它会自动继承父类所有的指定初始化器。 + +```swift +class Animal { + var legs: Int + var name: String + var age: Int + + init(name: String, age: Int, legs: Int) { + self.legs = legs + self.age = age + self.name = name + } + + init(name: String, age: Int) { + self.legs = 4 + self.age = age + self.name = name + } + + convenience init(name: String) { + self.init(name: name, age: 1, legs: 4) + } +} + +class Cat: Animal { + +} +// Cat 继承父类所有的指定初始化器 +var cat = Cat(name: "淘气", age: 3, legs: 4) +var cat1 = Cat(name: "淘气", age: 3) +// 子类自动继承所有的父类便捷初始化器 +var cat2 = Cat(name: "淘气") +``` + +②如果子类提供了父类所有指定初始化器的实现(要么通过方式①继承,要么重写) + +* 子类自动继承所有的父类便捷初始化器 + +③就算子类添加了更多的便捷初始化器,这些规则仍然适用 + +④子类以便捷初始化器的形式重写父类的指定初始化器,也可以作为满足规则②的一部分 diff --git a/14 初始化.playground/contents.xcplayground b/14 初始化.playground/contents.xcplayground new file mode 100644 index 0000000..cf026f2 --- /dev/null +++ b/14 初始化.playground/contents.xcplayground @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/14 初始化.playground/playground.xcworkspace/contents.xcworkspacedata b/14 初始化.playground/playground.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..ca3329e --- /dev/null +++ b/14 初始化.playground/playground.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/14 初始化.playground/playground.xcworkspace/xcuserdata/jiulinxiri.xcuserdatad/UserInterfaceState.xcuserstate b/14 初始化.playground/playground.xcworkspace/xcuserdata/jiulinxiri.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100644 index 0000000..2cd1650 Binary files /dev/null and b/14 初始化.playground/playground.xcworkspace/xcuserdata/jiulinxiri.xcuserdatad/UserInterfaceState.xcuserstate differ