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

前端之家收集整理的这篇文章主要介绍了Swift:面向对象(继承与构造方法)前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

一、 继承

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,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"

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

猜你在找的Swift相关文章