[绍棠_swift] Swift中的继承、构造器

//

//  ViewController.swift

//  Learn_Swift_4

//

//  Created by Coco on 2017/7/24.

//  Copyright © 2017 Coco. All rights reserved.

//


import UIKit


class ViewController: UIViewController {

    

    class Person1 {         /// 基类, 不继承任何类, person属于一个基类,

        func eat() {

            print("eat a pig")

        }

    }

    

    // 继承, swift为单继承,

    class XiaoMing1: Person1 {

        var name = "XiaoMing1"

        

    }

    

    // 重写, 必须加关键字 override

    class XiaoMing: Person1 {

        override func eat() {

            super.eat();    // super 调用父类的属性与方法

            print("XiaoMing eat a pig")

        }

    }

    

/*

     重写属性(存储属性与计算属性)

     可以用getsetwillSetdidSet进行属性重写

     可以将一个只读属性重写为一个读写属性,不可以将一个读写属性重写为一个只读属性

     子类重写父类的属性时, 不管父类是计算属性还是存储属性, 重写的过程就是重写其中的get/set, 子类的override都是计算属性的格式

 */


    override func viewDidLoad() {

        super.viewDidLoad()

        // Do any additional setup after loading the view, typically from a nib.

        

        var xy = XiaoMing()

        xy.eat()

        

        class Person2 {

            var name: String {

                set {

                    print("person2 Set ")

                }

                get {

                    return "Person2"

                }

            }

            var age: Int = 10       // 常量存储属性

            var height: Int = 175   // 变量存储属性

        }

        

        class XiaoMing2: Person2 {

            override var name: String {

                set {

                    super.name = newValue   // 将父类的值设置为新值

                    print("XiaoMing2 set")

                }

                get {

                    return "XiaoMing2"

                }

            }

            

            override var age : Int {    // 如果父属性是var的话, 必须有getset

                get {

                    print(super.age)

                    return 20

                }

                set {

                    super.age = newValue

                }

            }

            

            override var height: Int {

                didSet {

                    print("didSet ----- \(oldValue)")

                }

                willSet {

                    print("willSet ----- \(newValue)")

                }

            }

        }

        

        var xm2 = XiaoMing2()

        xm2.name = "XM_2"

        xm2.age = 30

        xm2.height = 166

        print("xm2的各个值 \(xm2.name, xm2.age, xm2.height)")

        

        // 防止重写(final

        // 可将final写在属性, 方法, 类等前面

        class Person3 {

            final var name = "Person3"

        }

        

        class XiaoMing3 {

//            override var name = "XM"          // 这样会报错

        }

        

        // Mark:-   构造器(person4是指定构造器)

        class Person4 {

            var name: String    // 必须初始化, 或者在构造器函数中初始化

            init() {        // 无返回值

                name = "Coco"

            }

            

            // 带参数

            init(name: String) {        // 默认是以参数名作为外部参数名的

                self.name = "Hello" + name          // self Javathis

            }

            

            // 带可选参数。 可选类型:可以为空, 也可以以后赋值, 初始化为nil

            var age: Int = 10

            init(name: String, age:Int?) {

                self.name = name

                self.age = age!     // 可选参数必须确定有(加!号)才能赋值

            }

        }

        

        var p4 = Person4()        // 默认就是没有括号的

        var p4_1 = Person4(name: "BY")      // 参数名作为外部参数名

        var p4_2 = Person4(name: "BY", age: 20)

        

/*

         指定构造器与便利构造器

         指定构造器:每个类必须至少有一个, 用来确保所有值都进行初始化,(会根据父类的继承关系往上调用, 完成父类的初始化)(person4

         便利构造器(加convenience关键字):辅助性的构造器 可以用来同一个类中的指定构造器, 也可以用来创建一个有特定输入的实例

 */

        class Person5 {

            var name: String        // 必须初始化, 或者在指定构造器函数中初始化

            

            init(name: String) {        // 指定构造器

                self.name = "Hello" + name

            }

            

            convenience init(name: String, height: Int) {       // 便利构造器, 不需要全部初始化成员变量

                self.init(name: name)

                print("height的高度 \(height)")

            }

        }

        

        var p5 = Person5(name: "BY")

        var p5_1 = Person5(name: "BY", height:180)

/*

         构造器链:规范指定构造器与便利构造器间的调用关系

         1> 规则一: 指定构造器必须调用其父类的指定构造器

         2> 规则二: 便利构造器必须调用同一类中调用的其他构造器

         3> 规则三: 便利构造器必须以调用一个指定构造器结束

         

         总结指定构造器是向上调用的, 便利构造器是横向调用的

         

         两段式构造过程

         第一个阶段:每个存储型属性通过引入它们的类的构造器来设置初始值。

         第二阶阶段:当每一个存储型属性值被确定后,二阶段开始,它给每个类一次机会在新实例准备使用之前进一步定制它们的存储型属性。

         

         OC不同, Swift中子类不会默认继承父类的构造器. (但如果满足以下2个条件会自动继承)

         1)如果子类没有定义指定构造器, 那么他将主动继承父类的

         2)如果子类提供了所有父类指定构造器的实现, 那么自动继承父类的便利构造器

 */

        class Father {

            init() {

                print("father init")

            }

            

            convenience init(name: String) {

                self.init()

                print("father convenience init")

            }

        }

        

        class Son: Father {

            override init() {   // 子类实现了父类的全部指定构造器, 因而会自动继承父类的便利构造器

                print("son init")

            }

        }

        

        var son1 = Son()

        var son2 = Son(name: "BY")      // 自动继承了父类的便利构造器

        

        // 通过闭包和函数来设置属性的默认值

        // 闭包的一般格式

        class SomeClass {

            let someProperty: Int = {   // 整个花括号表示一个闭包

                return 0

            }()         // 这个小括号不能丢, 表示立即执行闭包。并返回值。

        }

/*

         1)如果某个存储属性的值需要特别定制, 则可以使用闭包或全局函数类提供默认值.

         2)当类型创建时, 闭包或函数会被调用,他们的返回值会被当做默认值赋值给这个存储属性.

         3)使用闭包时, 实例的其他部分并没有初始化, 因而不能在闭包里面访问:其他实例属性/self属性/实例方法等.

 */

        class Person6 {

            let name: String = {        // 可以在闭包里面做一些复杂的初始化工作

                let firstName = "B"

                let lastName = "Y"

                return firstName + lastName

            }()

        }

        var p6 = Person6()

        print(p6.name)

        

        // 析构(反初始化)deinit

/*

         在一个类实力被释放之前, 反初始化函数被立即调用

         每个类只有一个反初始化函数, 不带任何参数。且不允许主动调用。

         子类继承了父类的反初始化函数(先释放子类--》父类)

         反初始化方法能访问该实例的所有属性

 */

        class Person7 {

            var myMoney:Int

            init() {

                myMoney = 10

            }

            deinit {

                myMoney = 0 // 可以访问类中的变量, 但这句没用。因为销毁了, 成员变量即不存在了

                // 可以做一些清理工作

            }

        }

        var p: Person7? = Person7()

        print("person7的值  \(p!.myMoney)")

        p = nil         // 可选类型才能设置为nil

//        print("Person7的值2 \(p!.myMoney)")     // 错误, 会造成crash

        

    }


    override func didReceiveMemoryWarning() {

        super.didReceiveMemoryWarning()

        // Dispose of any resources that can be recreated.

    }

}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值