• Swift—默认构造函数-备


    结构体和类的实例在构造过程中会调用一种特殊的init方法,称为构造函数。构造函数没有返回值,可以重载。在多个构造函数重载的情况下,运行环境可以根据它的外部参数名或参数列表调用合适的构造函数。
    默认构造函数
    结构体和类在构造过程中会调用一个构造函数,即便是没有编写任何构造函数,编译器也会提供一个默认的构造函数。下面看示例代码:

     
    1. class Rectangle {       
    2.     var  Double  = 0.0   
    3.     var height: Double = 0.0   
    4. }  
    5. var rect = Rectangle()   //创建实例,并调用默认构造函数init()  
    6. rect.width = 320.0      
    7. rect.height = 480.0   
    8. print("长方形:(rect.width) x (rect.height)")  
    9. Rectangle()表示调用了某个方法,这个方法就是默认构造函数init()。  
    10. 事实上,在Rectangle的定义过程中省略了构造函数,相当于如下代码:  
    11. class Rectangle {     
    12.     var  Double  = 0.0   
    13.     var height: Double = 0.0   
    14.   
    15.   init() {          
    16.      }  
    17. }  

    如果Rectangle是结构体,则它的定义如下:
    struct Rectangle {
        var Double = 0.0
        var height: Double = 0.0
    }
    而结构体Rectangle的默认构造函数与类Rectangle的默认构造函数是不同的,相当于如下代码:

     
    1. struct Rectangle {  
    2.     var  Double = 0.0  
    3.     var height: Double = 0.0      
    4.     init() {           
    5.     }      
    6.     init( Double, height: Double) { //有参数的构造函数  
    7.         self.width   = width  
    8.         self.height  = height  
    9.     }  
    10. }  

    要调用哪个构造函数是根据传递的参数名和参数类型决定的。

    在构造函数中可以使用构造函数代理帮助完成部分构造工作。类构造函数代理分为横向代理和向上代理,横向代理只能在发生在同一类内部,这种构造函数称为便利构造函数。向上代理发生在继承的情况下,在子类构造过程中,要先调用父类构造函数初始化父类的存储属性,这种构造函数称为指定构造函数。 

    构造函数调用规则

     
    1. Person和Student类示例:  
    2.   
    3. class Person {  
    4.   
    5.     var name: String  
    6.   
    7.     var age: Int      
    8.   
    9.     func description() -> String {  
    10.   
    11.         return "(name) 年龄是: (age)"  
    12.   
    13.     }  
    14.   
    15.     convenience init () {         //便利构造函数  
    16.   
    17.         self.init(name: "Tony")  
    18.   
    19.         self.age = 18  
    20.   
    21.     }  
    22.   
    23.     convenience init (name: String) { //便利构造函数  
    24.   
    25.         self.init(name: name, age: 18)  
    26.   
    27.     }  
    28.   
    29.     init (name: String, age: Int) {       //指定构造函数  
    30.   
    31.         self.name = name  
    32.   
    33.         self.age  = age  
    34.   
    35.     }  
    36.   
    37. }   
    38.   
    39. class Student: Person {  
    40.   
    41.     var school: String  
    42.   
    43.     init (name: String, age: Int, school: String) {       //指定构造函数  
    44.   
    45.         self.school = school  
    46.   
    47.         super.init(name: name, age: age)  
    48.   
    49.     }  
    50.   
    51.     convenience override init (name: String, age: Int) {//便利构造函数  
    52.   
    53.         self.init(name: name, age: age, school: "清华大学")  
    54.   
    55.     }  
    56.   
    57. }   
    58.   
    59. let student = Student()  
    60.   
    61. print("学生: (student.description())")   

    构造函数之间的调用形成了构造函数链,如图所示。

    Swift限制构造函数之间的代理调用的规则有3条,如下所示。

    指定构造函数必须调用其直接父类的的指定构造函数。从图可见,Student中的④号指定构造函数调用Person中的③号指定构造函数。

      •  

      • 便利构造函数必须调用同一类中定义的其他构造函数。从图可见,Student中的⑤号便利构造函数调用同一类中的④号便利构造函数,Person中的①号便利构造函数调用同一类中的②号便利构造函数。

      • 便利构造函数必须最终以调用一个指定构造函数结束。从图可见,Student中的⑤号便利构造函数调用同一类中的④号指定构造函数,Person中的②号便利构造函数调用同一类中的③号指定构造函数。

    • ==================================================
    • Swift中的子类构造函数的来源有两种:自己编写和从父类继承。并不是父类的所有的构造函数都能继承下来,能够从父类继承下来的构造函数是有条件的,如下所示。

      • 条件1:如果子类没有定义任何指定构造函数,它将自动继承所有父类的指定构造函数。

      • 条件2:如果子类提供了所有父类指定构造函数的实现,无论是通过条件1继承过来的,还是通过自己编写实现的,它都将自动继承所有父类的便利构造函数。

      下面看示例代码:

       

       
      1. class Person {             
      2.   
      3.     var name: String  
      4.   
      5.     var age: Int  
      6.   
      7.       
      8.   
      9.     func description() -> String {  
      10.   
      11.         return "(name) 年龄是: (age)"  
      12.   
      13.     }  
      14.   
      15.     convenience init () {  
      16.   
      17.         self.init(name: "Tony")  
      18.   
      19.         self.age = 18  
      20.   
      21.     }  
      22.   
      23.     convenience init (name: String) {  
      24.   
      25.         self.init(name: name, age: 18)  
      26.   
      27.     }  
      28.   
      29.     init (name: String, age: Int) {         
      30.   
      31.         self.name = name  
      32.   
      33.         self.age  = age  
      34.   
      35.     }  
      36.   
      37. }  
      38.   
      39.    
      40.   
      41. class Student: Person {  
      42.   
      43.     var school: String  
      44.   
      45.     init (name: String, age: Int, school: String) {  
      46.   
      47.         self.school = school  
      48.   
      49.         super.init(name: name, age: age)  
      50.   
      51.     }  
      52.   
      53.     convenience override init (name: String, age: Int) {    
      54.   
      55.         self.init(name: name, age: age, school: "清华大学")  
      56.   
      57.     }  
      58.   
      59. }  
      60.   
      61.    
      62.   
      63. class Graduate: Student {      
      64.   
      65.     var special: String = ""  
      66.   
      67. }  

      来看看符合条件1的继承,Graduate继承Student,Graduate类没有定义任何指定构造函数,它将自动继承所有Student的指定构造函数。符合条件1后,Graduate从Student继承了如下指定构造函数:

      init (nameString, ageInt,schoolString)

      再看符合条件2的继承,由于Graduate实现了Student的所有指定构造函数,Graduate将自动继承所有Student的便利构造函数。符合条件2后,Graduate从Student继承了如下3个便利构造函数:

      init (nameString, ageInt)

      init (nameString)

      init ()

      Student继承Person后有4个构造函数。

      条件1对Student不满足,因为它有指定构造函数,Student类中的便利构造函数init (name: String, age: Int)满足了条件2,它实现了父类指定构造函数init (name: String, age: Int)。另外,由于子类构造函数与父类构造函数参数相同,需要使用override关键字,表示子类构造函数重写(overriding)了父类构造函数。

      由于Student类实现了父类指定构造函数,因此也继承了父类的另外两个便利构造函数。

  • 相关阅读:
    ThinkPHP安全规范指引
    正则表达式:不能包含某些特殊字符串
    头晕是因为虚 ( ̄^ ̄゜)
    vs code中文扩展包
    table-cell width:1% 深入理解
    C#使用NPOI操作Excel
    C#利用LumenWorks.Framework.IO.Csv读取CSV文件
    发送邮件代码
    .net 集合详解
    EF Code First:数据更新最佳实践
  • 原文地址:https://www.cnblogs.com/isItOk/p/5454159.html
Copyright © 2020-2023  润新知