程序员

Swift构造方法

2020-07-19  本文已影响0人  奔跑的鸿
init(参数列表){ 初始化代码 }

注意

  1. 构造方法的作用仅仅是用于初始化属性, 而不是分配内存, 分配内存是系统帮我们做的
  2. 构造方法是隐式调用的, 通过类名称() 形成创建一个对象就会隐式调用 init() 构造方法
  3. 如果所有的存储属性都有默认值, 可以不提供构造方法, 系统会提供一个隐式的构造方法;
  4. 如果存储属性可以提供默认值, 那么提倡大家使用设置默认值的方法, 这样可以简化代码,不用写构造方法
class Person {
    var name: String = "hjq"
//    var age: Int = 20
    var age:Int
    func description() -> String {
        return "name = \(name) age = \(age)"
    }

    init() {
        print("init")
        age = 30
    }
}

// 1.分配内存; 2.初始化name和age; 3.构造方法是隐式调用的
var p = Person()
print(p.description())
print(p.age)
class Person2 {
    var name:String
    var age:Int
    func description() -> String {
        return "name = \(name) age = \(age)"
    }
   
    init(age:Int, name:String)
    {
        self.name = name
        self.age = age
    }
    func setName(name:String, age:Int)
    {
        self.name = name
        self.age = age
    }
}
var p2 = Person2(age: 25, name: "hjq")
p2.setName(name: "hjq", age: 30)
print(p2.description())

以上存储属性都没有提供默认值,必须提供构造方法,而构造方法是带参数的,所以创建对象时必须带参数来初始化存储属性,而不能用Person2()

struct Rect {
    var width:Double
    var height:Double
    /*
    // 系统默认会提供一个类似的方法
    init(width:Double, height:Double)
    {
        self.width = width
        self.height = height
    }
    */
}
var r = Rect(width: 20, height: 20)

以上存储属性都没有默认值,故必须用默认的逐一构造器初始化结构体,不存在Rect()的方式初始化结构体。
如果在结构体中自定义了构造方法, 那么系统不会生成默认的逐一构造器。
如果给存储属性提供了默认值, 系统还是会提供默认的逐一构造器

struct Rect2 {
    var width:Double, height:Double
    init(width:Double, height:Double)
    {
        self.width = width
        self.height = height
    }
    init()
    {
//        self.width = 0.0
//        self.height = 0.0
        //构造器代理
        self.init(width: 0, height: 0)
    }
    func show()
    {
        print("width = \(width) height = \(height)")
    }
}
var r2 = Rect2()
r2.show()
var r3 = Rect2(width: 100, height: 100)
r3.show()
class Person {
    var name:String
    var age:Int
    //指定构造方法都是以init开头
    init(name:String, age:Int)
    {
        self.name = name
        self.age = age
    }
    //1.如果是值类型没问题, 称之为构造器代理;
    //2.但是如果是引用类型会报错, 需要在前面加上 convenience关键字;
    //3.被convenience关键字修饰的构造方法称之为便利构造器, 通过调用其他构造方法来初始化;
    //4.反而言之, 便利构造器中一定是调用其他构造方法初始化的, 一定要出现self.init
    convenience init()
    {
        self.init(name: "hjq", age: 26)
    }
    //类可以拥有多个构造方法
    init(name:String)
    {
        self.name = name
        self.age = 0
        //不能再指定构造方法中调用便利构造器方法
        //换言之,指定构造方法中不能出现self.init
//        self.init()
    }
    
    convenience init(age:Int)
    {
        //可以在便利构造器中调用指定构造器
//        self.init(name: "hjq", age: 24)
        self.init()
    }
    // 便利构造器不能和指定构造器同名
    //    convenience init(name:String)
    //    {
    //    }
}
class Man {
    var name:String
    //指定构造器
    init(name:String)
    {
        self.name = name
    }
    convenience init(){
        self.init(name: "hjq")
    }
}
class SuperMan: Man {
    var age:Int
    
    // 注意:
    // 1.默认情况下基类的构造方法不会被继承
    // 2.基类的存储属性只能通过基类的构造方法初始化
    // 3.初始化存储属性时必须先初始化当前类再初始化父类
    // 4.不能通过便利构造器初始化父类, 只能通过调用指定构造器初始化父类
    //指定构造器
    init(age:Int) {
        self.age = age
        super.init(name: "han")    //必须调用父类的指定构造器
//        super.init()    //不能调用父类的便利构造器
    }
}
class Man2 {
    var name:String
    //指定构造器
    init(name:String) {
        self.name = name
    }
    convenience init(){
        self.init(name: "HaRi")
    }
}
class SuperMan2: Man2 {
    var age:Int
    //指定构造器
    init(age:Int) {
        self.age = age
        super.init(name: "xiaohange")
    }
    convenience init()
    {
        self.init(age: 25)
    }
    convenience  init(name: String, age: Int) {
        //调用当前类构造器一定能够初始化所有属性
//        self.init(age: 30)
        //便利构造器中只能通过self.init来初始化, 不能使用 super.init
        //因为调用父类构造器不一定完全初始化所有属性(子类持有)
//        super.init(name: "han")
        self.init()
    }
}
class Man3 {
    var name:String
    //指定构造方法
    init(name:String) {
        self.name = name
    }
    //便利构造方法
    convenience init(){
        self.init(name: "hello world")
    }
}

class SuperMan3: Man3 {
    var age:Int
    init(age:Int) {
        print("SuperMan第一阶段开始")
        //对子类引入的属性初始化
        self.age = age
        
        //代码会报错, 因为调用self.name之前还没有对父类的name进行初始化
        //即便在这个地方修改, 也会被后面的初始化语句覆盖
//        if age > 30 {
//            self.name = "hjq"
//        }
        //对父类引入的属性进行初始化
        super.init(name: "han")
        
        print("SuperMan第二阶段开始")
        if age > 30 {
            self.name = "hello xiaohange"
        }
    }
}
class Person7 {
    var name:String
    required init(name:String){
        self.name = name
    }
}
class SuperMan7: Person7 {
    var age:Int
    init() {
        self.age = 24
        super.init(name: "hjq")
    }
    required init(name: String) {
        self.age = 24
        super.init(name: name)
    }
}
var sm7 = SuperMan7(name: "hjq")
上一篇 下一篇

猜你喜欢

热点阅读