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

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

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-11-08 16:33:30

Swift:面向对象(继承与构造方法)的相关文章

57 面向对象继承中构造方法的关系

1 class Demo1_Extends{ 2 public static void main(String[] args) { 3 Dog d = new Dog(); 4 } 5 } 6 7 class Animals extends Object{ 8 public Animals(){ 9 super() // 默认继承 Object类 10 System.out.println("父类无参构造方法"); 11 } 12 } 13 14 class Dog extends A

Php面向对象 – 继承和重写

继承: php中,通过在类上,使用特殊的操作达到目的. 通过在定义类时,利用extends来指明当前类对象继承那个类的对象. 例子: class C { public  $p_c =  "value c"; } class D extends C { public  $p_d = "value d"; } $o =  new D; var_dump($o->p_c) var_dump($o->p_d) 输出:string(7) "value c

Java面向对象㈡ -- 继承与多态

Java的继承是通过extends和implement来实现的,Java不支持多继承,但是Java支持多层继承以及多实现(接口).Java继承有一个关键字super是用来指向父类.Java继承衍生出覆盖的概念.覆盖被用来支持多态.实际开发中Java通常继承于抽象类,实现于接口.如果不希望一个类被继承,或者一个方法被覆盖,或者一个成员变量被改变,就可以用final修饰.这里只说明两个问题:1,重载和覆盖的区别重载和覆盖的区别:重载发生在同一个类之中,重载要求函数名相同,参数不同(参数个数||参数类

Swift面向对象的类型

1.类 2.结构体(struct) 3.枚举(enum) 在swift语言中通过类和结构体实现面向对象,在Swift语言中,枚举也具有面向对象的特性 示例和对象 在面向对象中,将类创建对象的过程称为实例化,因此将对象称为实例化,但是在swift中,枚举和结构体不能称为对象,因为结构体和枚举并不是彻底的面向对象类型,而是只包含了一些面向对象的特定,例如,在Swift中继承只发生在类上,结构体和枚举不能继承

.Net学习 第2季02 C#面向对象继承1

.Net 视频学习第2季 C#面向对象 面向对象继承1 查找类的命名空间快捷键:alt+shift+F10 项目A中有类X,要在项目B中使用X的话,首先在项目B的引用当中添加项目A,然后在项目B的代码中添加using A;(假设项目A类X的命名空间就是A)或者在使用X时采用A.X的格式. 记录运行时间 Stopwatch sw = new Stopwatch(); sw.Start(); // 代码 sw.Stop(); Console.WriteLine(sw.Elapsed); Start(

js面向对象继承

前言 最近看到js面向对象这章节了,主要学习了原型和面向对象继承关系,为了梳理自己的知识逻辑,特此记录. js的面向对象 先说说我目前了解的js创建对象方法 1.写一个函数,然后通过new创建对象 2.字面量的方式 如果想要复用的话,可能会用到工厂方法 工厂方法每次都要创建对象 并返回 构造方法创建对象方法可以更简洁 然而构造方法用实现实例间共享共同的方法,比较麻烦 原型可以实现实例共享所有属性 每个函数都有指向原型对象的指针,如果将一个函数的原型属性赋值给另外函数的实例,函数的原型将指向另外一

Swift 面向对象解析(一)

面向对象总体概括: Swift 不仅能够面向过程编程,也能够面向对象编程(OOP).面向对象其实就是“以对象为核心”,把我们的客观世界想着是由一个个对象组成的,面向对象编程则为对象提供了属性和方法,属性就是为了描述对象的一些状态,方法则是告诉你对象该做什么.面向对象和核心就是“类”和“对象”!在我刚接触编程的时候,其实我也很容易把这东西混淆了,你要也是刚接触编程,能帮到你的,我觉得反而是时间.你要实在是有点难理解,就别去钻牛角尖,也许明天因为某个东西你就会恍然大悟.超喜欢那种感觉! 面向对象的三

附录A培训实习生-面向对象基础(2):构造方法和带参数的构造方法

构造方法,又叫构造函数,其实就是对类进行实例化.构造方法与类同名,无返回值,也不需要void,在new时候调用.也就是说,就是调用构造方法的时候. 所有类都有构造方法,如果你不编码则系统默认生成空的的构造方法,如你有定义构造方法,那么默认的构造方法就会失效. 有参数的构造方法:比如我们希望每个小猫一诞生都有姓名,那么就应该写一个有参数的构造方法. 这是一个有参数的构造方法,可以看下: 1 using System; 2 using System.Collections.Generic; 3 us

java面向对象(继承)

继承 对某一批类的抽象,减少代码量,便于方法的修改,类的管理 子类不能继承父类:①构造方法②私有属性和方法③使用默认修饰符不在同包下 继承初始化:父类属性->父类构造方法->子类属性->子类构造方法 继承有哪些:①重载②重写③接口④父类对象引用指向子类对象 重写规则:①方法名一样②参数列表相同③返回值类型相同或是其子类④访问修饰权限不能严于父类 private(本类)>default(同包)>protected(同包及子类)>public(全部) super / thi