您的位置:首页 > 移动开发 > Swift

Swift -- 8.2 类的构造与析构

2016-06-28 15:22 417 查看
类中的存储属性必须要在构造过程中设置初始值,加上继承的的属性,类的构造过程比较复杂

析构器 deinit函数

在实例销毁之前被系统调用,实例不能自己调用

值类型的构造器可以直接调用一个其他的构造器,但是类的构造器不可以,必须要用convenience来变成便利构造器,然后才能调用其他的构造器

如果有父类,需要使用super来调用父类的构造器

class Apple1 {

var name:String!
var weight:Double

init(name:String, weight:Double){
self.name = name
self.weight = weight
}

init(nn name:String, weight:Double){//构造器重载
self.name = name
self.weight = weight
}

convenience init(n name:String, w weight:Double){//变成便利构造器来调用其他构造器
self.init(name:name, weight:weight)
self.name  = name
}

}

class Pear: Fruit {
init(weight:Double){
super.init()//调用父类的构造器
self.weight = weight
}
}


  

两段式构造

swift类的构造需要两个阶段完成

第一阶段:先为存储属性分配内容,使用本类的构造器初始化由本类定义的存储属性,然后沿着构造器链向上,逐个调用各父类构造器初始化对应父类定义的存储属性

第二阶段:从最顶层开始,沿着顶部构造器链向下,每个构造器都可以再次修改存储属性

为了保证两段式构造顺利完成,swift提供了四种安全检查

1:指定构造器必须先初始化当前类中定义的实例存储属性,然后才能向上调用父类构造器

2:指定构造器必须先向上调用父类构造器,然后才能对继承得到的属性赋值

3:便利构造器必须先调用同一个类的其他构造器,然后才能对属性赋值

4:构造器在第一阶段完成之前,不能调用实例方法,不能读取实例属性

swift类的构造器规则比较繁琐,因此处理起来比较容易出错,但如果程序显式地为所有实例存储属性指定初始值,定义构造器时就会简单得多,而且可以直接利用系统默认的构造器(hiahiahia 因为这样做的话,只需要把所有的构造器都写在第一行就永远不会出错了hiahiahia)

class A{
var name : String
init(name:String){
self.name = name
}
}
class B: A {
var age:Int
init(age:Int){
self.age = age
super.init(name: "")
self.run()

}
func run(){
print("run");
}
}

var bb = B(age: 22)


  

构造器的继承和重写

构造器的继承规则

1 如果子类没有提供任何构造器,那么它会继承父类的所有指定构造器和便利构造器

2 如果子类实现了父类的所有指定构造器(比如说使用方法1或是重写来实现),那么它将继承父类的所有便利构造器

反而言之,如果子类自己写了构造器,并且没有重写父类的指定构造器,那么它就不能继承父类的构造器

class F
{
var name : String
var weight : Double
init(name:String, weight:Double){
self.name = name
self.weight = weight
}
init(n name:String){
self.name = name
self.weight = 0.0
}
convenience init(){
self.init(n:"")
self.weight = 1.0
}
}

class App: F {
var color : String
override init(name:String, weight:Double){
self.color = ""
super.init(name: name, weight: weight)
}
override init(n name:String){
self.color = ""
super.init(n: name)
}
init(name:String, weight:Double, color:String){
self.color = color
super.init(name: name, weight: weight)
}
convenience init(name:String, color:String){
self.init(name:name, weight:0.0, color:color)
}
}

class Fuji: App {
var vitanim : Double = 0.21
}
var ff = App()
ff.weight
var tt = Fuji(name: "", color: "")

//子类的构造器不能与父类的构造器的形参列表相同,如果相同需要添加override关键字。但是如果父类的构造器是便利构造器就没有事
class F2 {
var name : String
init(){
self.name = ""
}

convenience init(name:String){
self.init()
}
}

class F3: F2 {
var color : String
init(name:String){//这个构造器父类中也有,不过父类中是便利构造器,所以子类中依然可以使用
self.color = ""
super.init()
}
}


  

类与可能失败的构造器

可能失败的构造器必须满足的两个条件

1 该类中所有实例存储属性都已被赋值

2 所有的构造器调用都已经被执行(return nil 不能位于self.init 或 super.init代码之前)

如果子类调用父类的可能失败的构造器,那么如果父类的构造器return nil,那么子类构造器中之后的代码都不会被执行

在重写可能失败的构造器的时候,可以重写成可能失败的构造器,也可以重写成普通构造器

class User {
var name : String
init?(name:String){
self.name = ""
if name.isEmpty {
return nil
}
self.name = name
}
}

class Student: User {
var grade : Int!
init!(name:String, grade:Int){
super.init(name: name)//如果这个构造器失败,那么之后的代码都不会被执行
if grade < 1{
return nil
}
self.grade = grade
}
}
//所以在类中,可能失败的构造器可以调用普通的构造器,普通的构造器不能调用可能失败的构造器

class C1 {
var name : String
init!(name:String){
self.name = ""
if name.isEmpty{
return nil
}
self.name = name
}
}

class C2: C1 {
var color : String
init?(name:String, color:String){
self.color = ""
super.init(name: "")

}
init(color:String){
self.color = color
super.init(name: "")//虽然这里没有报错,但是使用实例的时候会出错的
}
}
let ccccc = C2(name: "", color: "")


  

子类必须包含的构造器

使用required来标记构造器,表示子类构造器必须包含这个构造器

可以通过重写和继承来得到

class Fruit5 {
var name:String
required init(name:String){
self.name = name
}

}

class Apple5: Fruit5 {
var weight : Double
init(weight:Double){
self.weight = weight
super.init(name: "")
}

required init(name: String) {//不写这个构造器会报错
self.weight = 0
super.init(name: name)
}
}


  

析构器

deinit

在实例被销毁之前调用

析构器是系统自动调用的,实例不可以自己调用

子类的析构器执行结束时将自动调用父类的析构器

class T1 {
var name : String = "nn"
deinit{
print("the T1 is deinit")
}
}

class T2: T1 {
deinit{
print("the T2 is deinit")
}
}
var ap:T2? = T2()
ap!.name
ap = nil
//the T2 is deinit
//the T1 is deinit


  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: