构造函数 init

本文详细介绍了 Swift 中构造函数 init 的使用规则,包括 init 的特性、指定构造器与便利构造器的区别,以及如何在继承中使用 init。强调了在初始化过程中属性的初始化要求,以及 override 的特殊规定。通过示例展示了结构体和类在构造过程中的不同行为,帮助读者深入理解 Swift 的构造流程和初始化规则。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


/* 构造函数 init

init函数,没有返回值,不能用func修饰,不能通过实例调用init,只能用init调用其他重载的init

✨关于override的特殊规定,普通方法必须override,指定构造必须override,便利构造不能写override修饰符。

当override一个required的构造函数时,不需要写override。override一个required的构造时,所有子类都需要加required。

required构造函数,可以通过继承获得,而不需要一定去重写。但是只要写了,必须加required。

另外,required只能用于init函数。

在定义了自己的指定init后,默认的init就没有啦


init函数结构体,枚举都可以有。但是deinit析构函数只能在类中才能有。

实例创建前,必须对所有的stored property进行初始化,这个可以在定义变量的时候赋初值

也可以在init函数中进行。


如果没有特殊需求,请在变量定义的时候初始化。在init中初始化的好处是,

1)可以在不同的重载函数init中初始化不同的值

2)在类继承的时候可以对初始化值进行修改。

3)另外,在定义时初始化 init中初始化都不会触发property observer

4)在初始化函数中可以对const的变量进行重新赋初值。


init中调用其他的self.init(必须加self)函数时,称为initializer delegation初始化代理

✨✨✨值类型的构造函数之间没有特殊规定。(结构体等),但是类中的init函数分为指定构造和便利构造。


类中因为多了继承的原因,为了保证所有的属性都被初始化,特做了如下规定:

构造其分为 Designated(指定,特定) initializerconvenience initializer:

1.若有父类,并且子类实现了指定构造器,必须在指定构造器中的初始化阶段1(所有子类属性初始化,见官网定义)最后调用super.init()

2.便利构造函数必须调用同一类中定义的其他构造器。包含指定构造器和便利构造器(该构造器调用了指定构造器)。

3.init函数可以调用instanceMethod,也可以对属性赋值,但是不可以在初始化阶段1(所有的变量都被初始化)之前。


✨✨总则:指定构造器必须向上代理。便利构造器必须横向代理(必须调用一个指定构造器结束)。


关于子类的继承(自己的理解):

1.在初始化的时候父类的属性尽量不要在子类中直接修改,当然在初始化阶段1后是可以修改的。

尽量调用super.init(var1:xx, var2:xx),反过来说如果在子类中直接初始化,继承的意义就不大了。

2.如果子类没有定义designated init,则子类继承所有父类的指定构造器,

如果定义了任意一个指定构造器,则所有的指定构造器将不会被继承✨✨

3.如果通过继承或者自己定义了父类的所有指定构造器,则子类会自动继承父类所有的便利构造器。

(注意便利构造器一定会调用指定构造器,这时调用的都是当前子类中的指定构造器)

反过来说,如果任何一个指定构造器没有在子类中被重新定义,则所有便利构造器不会被继承。

4.可以用reqired修饰符来要求子类必须实现某个init(类似C++的Interface),子类中必须要有required的init

可以重新定义父类中的required init,也可以通过继承获得

5.final一下,就不会在子类中被override,

  requried只能用于构造init,而final可以用于属性,除构造函数的任意函数,以及整个类

6.注意final lazy required前面在新版本中都不需要@,在OC中为了减少和C的冲突,OC的关键字都带@

*/


struct RectStruct

{

   var width:Int

   var height:Int

    

    init()//在前面加func会报错

    {

        width = 1 //类中的成员变量,初始化阶段1之后,所有属性必须被进行初始化,否则报错。

       height = 2

    }

    

   init(iw:Int, ih:Int)

    {

        self.init()//注意valueTypeinit时没有讲究的,但是类的就比较复杂。

    }

}

//var s = RectStruct(width:3, height:4) //写了自己的初始化函数后,默认的初始化函数不可用。


class Animal

{

   var name:String

   init(name:String)

    {

       self.name = name

        println("In class Animal designated init")

    }

    

   init(id:Int)

    {

        self.name ="default name!"

    }

    

    // convenience init

    convenience init()

    {

        self.init(name:"Animal"//convenience init必须调用一个designated init

        println("In Animal convenience init")

    }

}


class EmptyBird :Animal

{

    

}


var b = EmptyBird()

//In class Animal designated init

//In Animal convenience init

//一个空的子类会完全继承父类的指定构造器和便利构造器


class RealBird :Animal

{

   var canfly:Bool

    //var canrun:Bool = true 如果定义了这个属性,则要么在所有的designated init中赋初值

    //要么在定义时赋初值,否则会报错。

    

   init(name:String, canfly:Bool)

    {

       self.canfly = canfly

        // self.instanceMethod() instanceMethod不可以在初始化阶段1(所有的变量都被初始化),之前调用。

        super.init(name:name)//初始化阶段1的最后,不能放在self.canfly赋值的前面。

        println("In RealBird designated init")

        self.instanceMethod()

    }

    

   func instanceMethod()

    {

       self.canfly =true

    }

}

// var realbird = RealBird()

var realbird =RealBird(name:"maque", canfly:true)

//var realbird2 = RealBird(id:3) 如果子类中有一个指定构造函数,则父类中的指定构造函数不会被继承。


class NoDesignatedInit:Animal

{

    convenience init(test:Int)

    {

        self.init(id:3) //如果子类没有定义designated init,则子类继承所有父类的指定构造器

    }

}


class OlnyPartDesignatedInit:Animal

{

   var myvar:Int

   init(id:Int)

    {

        //在指定构造器中将所有的子类stored属性初始化完,方可调用完父类进行初始化后

       myvar = 3

       super.init(id:id)

//将所有的stored属性初始化一遍(初始化阶段1)后,可以进行再次赋值等其他操作。

        self.name"OlnyPartDesignatedInit"

    }

}

//只继承一个指定构造器,且没有继承,便利构造器调用的init(name:String)

//便利构造器无法被继承。

//ERROR var bird3 = OlnyPartDesignatedInit()


class OlnyPartDesignatedInit2:Animal

{

   init(name:String)

    {

       super.init(name:name)

        println("In class Animal designated init")

    }

}

//只继承一个指定构造器,且继承了便利构造器调用的init(name:String)

//便利构造器无法被继承。

//ERROR var bird3 = OlnyPartDesignatedInit2()

class AllDesignatedInit:Animal

{

   init(name:String)

    {

       super.init(name:name)

        println("In class Animal designated init")

    }

    

   init(id:Int)

    {

       super.init(id:id)

        self.name ="default name!"

    }

}

//结论,如果想让任何一个便利构造器被继承,则必须实现所有的指定构造器,否则不可以继承便利构造器。

var bird4 = AllDesignatedInit()



class RequiredClass

{

   var memInt:Int


   required init(myInt:Int)

    {

       memInt = myInt

    }


    required convenience init()

    {

       self.init(myInt:3)

    }

}


class SubClass : RequiredClass

{

    //required的构造函数可以通过继承来获得,

    //如果继承不到的情况,就必须写。比如只定义了部分指定构造,便利构造不会被默认继承

    //这时需要自己添加required的部分,添加时子类也要加上required的修饰。

}


//《完》

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值