Swift:面向对象(继承与构造方法)

本人录制技术视频地址:https://edu.csdn.net/lecturer/1899 欢迎观看。

一、 继承

1.  Swift中定义的类,如果不继承自任何类,它就是基类。这一点和objective-c中定义的类不一样,在objective-c中定义的类默认的基类是NSObject。
2.  重写父类的方法及属性,必须使用override的关键字(这样处理的话,更清晰了,很容易看出是父类的方法还是自己类中的方法)。
3.  如果在类,方法,属性 前面用final进行了修饰,就不允许被继承或者被重写。

类继承关系Demo:

class Animal {
    
    var speed : Int = 1
    
    func run() {
        println("Animal is running")
    }
}

class Dog: Animal {
    
    override var speed : Int {
        get {
            return super.speed
        }
        set {
            if newValue > 100 {
                super.speed = 100
            } else {
                super.speed = newValue
            }
        }
    }
    
    override func run() {
        println("Dog is running")
    }
}

二、 构造方法

在Swift中,存储属性在定义的时候必须要进行初始化工作,这一点我在Swift:面向对象(属性)中有提到过。如果不进行初始化的话,我们也可以在构造方法中完成初始化工作。

Swift中构造方法的特点:

1. 方法名字叫做init。

2. 没有func关键字。

3. 没有返回值。

Demo:

class Person {
    var name: String
    var age: Int
    
    init(name: String , age: Int) {
        self.name = name
        self.age = age
    }
}

var p = Person(name: "Rose", age: 30)

在本例中,有两个存储属性name和age,它们在定义的时候均没有完成初始化工作,但我们可以在init(name: String, age: Int) 这个构造方法中完成它们的初始化工作。self.name 和 self.age 就是定义的两个属性,而 name 和 age 就是外界传递过来的变量值。

三、 指定构造方法(Designated) 和 便利构造方法(Convenience

关于指定构造方法和便利构造方法的使用有很多规则。

1. 只有便利构造方法才能调用当前类的其他构造方法。

class Person {
    var name: String
    var age: Int
    
    init(name: String, age: Int) {
        self.name = name
        self.age = age
    }
    
    init(name: String) {
        self.init(name: name, age: 10)
    }
}

在上例中,试图在init(name: String) 这个构造方法中调用init(name: String, age: Int)这个构造方法,并且age的默认值是10。但是程序会直接报错。


可以看出,错误信息很明显,提示你在init(name: String) 构造方法之前加上convenience, 使这个构造方法变成便利构造方法即可。

2. 只有指定构造方法才能调用父类的构造方法

class Person {
    var name: String
    var age: Int
    
    init(name: String, age: Int) {
        self.name = name
        self.age = age
    }
    
    convenience init(name: String) {
        self.init(name: name, age: 10)
    }
}

class Jack: Person {
    convenience init(name: String) {
        super.init(name: name, age: 20)
    }
}

上例中,试图在Jack这个子类的 convenience init(name: String) 这个便利构造方法中调用父类Person的指定构造方法init(name: String, age: Int)。但是程序会报错。


所以,我们将Jack这个类中的convenience这个关键字去掉即可。让子类的直接构造方法调用父类的直接构造方法。

3. 有参的指定构造方法会覆盖调用默认的无参指定构造方法。

在Swift中定义的类中,都有一个默认的无参指定构造方法,只是没有显示出来。例如:

class Person {
}

它其实有一个 init(){}  指定构造方法,这也是为什么可以书写下面的代码完成对象的初始化工作。

var p = Person()

但是,如果你在代码中书写了有参指定构造方法,那么默认的无参指定构造方法将被覆盖掉。例如:

class Person {
    var name: String
    var age: Int
    init(name: String, age: Int) {
        self.name = name
        self.age = age
    }
}

此时你再调用
var p = Person()
这句代码将直接报错了。


但如果想不管调用无参构造方法还是有参构造方法都可以。那么你将默认的指定都早方法写出来即可。

class Person {
    var name: String
    var age: Int
    
    init() {
        self.name = "rose"
        self.age = 20
    }
    
    init(name: String, age: Int) {
        self.name = name
        self.age = age
    }
}

此时你调用如下代码,是完全可以的。

var p = Person()
var p2 = Person(name: "tick", age: 20)
4. 如果父类中存在有参的指定构造方法,子类的指定构造方法不会自动调用父类无参的指定构造方法

class Person {
    var name: String
    var age: Int
    
    init(name: String, age: Int) {
        self.name = name
        self.age = age
    }
}

class Jack: Person {
    override init(name: String, age: Int) {
        super.init()
    }
}

子类Jack的构造方法调用了父类的init默认无参的构造方法,将会直接报错。


所以我们在子类的构造方法中可直接调用父类的有参构造方法即可,代码如下:

super.init(name: name, age: age)

5. 常量属性只能在定义它的类的构造方法中初始化,不能在子类中初始化。

class Person {
    var name: String
    var age: Int
    let gender: String
    
    init(name: String, age: Int, gender: String) {
        self.name = name
        self.age = age
        self.gender = gender
    }
}

class Jack: Person {
    override init(name: String, age: Int, gender: String) {
        self.age = 10
        self.gender = "W"
        super.init(name: name, age: age, gender: gender)
    }
}

注意到在Person中定义的gender是一个常量,所以我试图在子类中对其进行初始化,是失败的。错误信息。



关于构造方法的知识,开起来似乎有点复杂,我们也可以分析下面两站流程图来分析上面我所提到的知识点。




四、 析构方法

Swift中的析构方法类似于objective-c中的dealloc的处理。

Demo:

class Dog {
    deinit {
        println("Dog Die")
    }
}

func oneDog() {
    var d = Dog()
}

println("New Dog")
oneDog()
println("Game Over")

oneDog函数执行完毕后,d变量被销毁,Dog对象就失去了强引用,也就被销毁了,会调用析构方法deinit

最终打印结果
"New Dog"
"Dog Die"
"Game Over"

注: 一个对象被释放前,先自动调用自己的析构方法,然后一层一层往上调用父类的析构方法

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
接着分析 (result (type_ident (component id='Bool' bind=Swift.(file).Bool))) (brace_stmt range=[re.swift:1:59 - line:14:1] (pattern_binding_decl range=[re.swift:2:5 - line:2:33] (pattern_named type='[UInt8]' 'b') Original init: (call_expr type='[UInt8]' location=re.swift:2:19 range=[re.swift:2:13 - line:2:33] nothrow (constructor_ref_call_expr type='(String.UTF8View) -> [UInt8]' location=re.swift:2:19 range=[re.swift:2:13 - line:2:19] nothrow (declref_expr implicit type='(Array<UInt8>.Type) -> (String.UTF8View) -> Array<UInt8>' location=re.swift:2:19 range=[re.swift:2:19 - line:2:19] decl=Swift.(file).Array extension.init(_:) [with (substitution_map generic_signature=<Element, S where Element == S.Element, S : Sequence> (substitution Element -> UInt8) (substitution S -> String.UTF8View))] function_ref=single) (argument_list implicit (argument (type_expr type='[UInt8].Type' location=re.swift:2:13 range=[re.swift:2:13 - line:2:19] typerepr='[UInt8]')) )) (argument_list (argument (member_ref_expr type='String.UTF8View' location=re.swift:2:29 range=[re.swift:2:21 - line:2:29] decl=Swift.(file).String extension.utf8 (declref_expr type='String' location=re.swift:2:21 range=[re.swift:2:21 - line:2:21] decl=re.(file).check(_:_:).encoded@re.swift:1:14 function_ref=unapplied))) )) Processed init: (call_expr type='[UInt8]' location=re.swift:2:19 range=[re.swift:2:13 - line:2:33] nothrow (constructor_ref_call_expr type='(String.UTF8View) -> [UInt8]' location=re.swift:2:19 range=[re.swift:2:13 - line:2:19] nothrow (declref_expr implicit type='(Array<UInt8>.Type) -> (String.UTF8View) -> Array<UInt8>' location=re.swift:2:19 range=[re.swift:2:19 - line:2:19] decl=Swift.(file).Array extension.init(_:) [with (substitution_map generic_signature=<Element, S where Element == S.Element, S : Sequence> (substitution Element -> UInt8) (substitution S -> String.UTF8View))] function_ref=single) (argument_list implicit (argument (type_expr type='[UInt8].Type' location=re.swift:2:13 range=[re.swift:2:13 - line:2:19] typerepr='[UInt8]')) )) (argument_list (argument (member_ref_expr type='String.UTF8View' location=re.swift:2:29 range=[re.swift:2:21 - line:2:29] decl=Swift.(file).String extension.utf8 (declref_expr type='String' location=re.swift:2:21 range=[re.swift:2:21 - line:2:21] decl=re.(file).check(_:_:).encoded@re.swift:1:14 function_ref=unapplied))) ))) (var_decl range=[re.swift:2:9 - line:2:9] "b" type='[UInt8]' interface type='[UInt8]' access=private readImpl=stored writeImpl=stored readWriteImpl=stored)
最新发布
06-10

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

秋恨雪

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值