美文网首页swift
swift4.1 系统学习十八 类(二)

swift4.1 系统学习十八 类(二)

作者: 小曼blog | 来源:发表于2018-10-26 12:26 被阅读16次

import Foundation

/*
本节继续学习 类
上一节学习了类的概念、类的属性和方法、继承的定义、类作为引用类型以及对属性的继承。
本节我们继续学习,主要内容如下:
1.对方法的继承
2.对下标的继承
3.类的初始化器方法

*/

// 1. 对方法的继承
/*
当子类B继承了父类A之后,B就可以访问父类的所有除了私有之外的方法。如果B想重写A的某个方法,可以使用
override关键字进行声明。
注意:
在swift语言支持方法重载,注意重载和重写的不同。重写父类的方法需要使用override关键字;而重载
父类的方法,只是方法名字与父类相同,参数类型或者参数个数与父类是不同的,也不需要override关键字。
*/

do {

print("\n------------1. 对方法的继承--------------\n")

class Animal {
    
    func eat() {
        print("动物都要吃食物")
    }
    
    func set(legs: Int) {
        print("这只动物有 \(legs)只脚")
    }
    
    /// 类型方法
    class func happy() {
        print("动物很开心")
    }
    
    /// 类型方法,该方法不能被子类重写
    static func run() {
        print("动物都会跑啊")
    }
}

class Cat: Animal {
    
    var name: String
    
    init(name: String) {
        self.name = name
    }
    
    /// 重写父类的方法
    override func eat() {
        print("这是一只小猫,它喜欢吃鱼,它的名字叫做\(name)")
    }
    
    /// 方法重载
    func set(legs: Int, eyes: Int) {
        print("这只猫有\(legs)只脚,\(eyes)只眼睛")
    }
    
    /// 重写父类的类型方法
    override  class func happy() {
        print("这只小猫很开心")
    }
}

// 使用
// 利用了类的多态特性,父类的对象指向子类的实例
let animal: Animal = Cat(name: "Tom")
// 这里调用的是Cat的eat的方法
animal.eat()
// 这里调用的是父类Animal的set(legs:)方法
animal.set(legs: 4)
// 报错:Extra argument 'eyes' in call
// animal无法访问Cat中重载的方法
//animal.set(legs: 4, eyes: 2)

// 这里就是正常的Cat的对象指向Cat的实例
let lihua: Cat = Cat(name: "狸花")
// 调用父类的set(:)方法
lihua.set(legs: 4)
// 调用cat自己的set方法
lihua.set(legs: 4, eyes: 2)


// 调用类型方法
//Animal的happy的方法
Animal.happy()
//Cat的happy方法
Cat.happy()
//Animal的run方法
Animal.run()
// Animal的run方法
Cat.run()

/*
 结果:
 这是一只小猫,它喜欢吃鱼,它的名字叫做Tom
 这只动物有 4只脚
 这只动物有 4只脚
 这只猫有4只脚,2只眼睛
 动物很开心
 这只小猫很开心
 动物都会跑啊
 动物都会跑啊
 */

}

// 注意:方法的多态性
// 当父类A的方法M调用了方法N,方法N被B重写,这个时候B调用M的时候,N是B类的,而不是A类的。
do {

print("-------多态特性------")

class F {
    
    func M() {
        print("这是F种的M")
        N()
    }
    
    func N() {
        print("这是F种的N")
    }
}

class C: F {
    
    override func N() {
        print("这是C中的N")
    }
}

let c = C()
c.M()
/*
 结果:
 这是F种的M
 这是C中的N
 */

}
/*
总结:
方法的调用在查找的时候,就是先找自己的方法中有没有这个方法,如果没有,再去父类中寻找,父类中
没有就再去父类的父类中去找,直到找到最后一个根类中,如果没有就返回报错,如果有,就调用这个方法。
像上面的例子中,查找过程是这样的:
c.M()
先去C中找M方法,没有,再去父类F中寻找,发现有,就调用它。当M执行到
N()
的时候,再去C中寻找N方法,发现有,直接返回,再继续执行M方法,直到遇到结束符大括号“}”.
*/

// 2. 对下标的继承
/*
之前我们在学习结构体的时候,就学习过了下标特性。
在类类型中,下标也能继承并且重写,由于下标方法本身类似于实例方法,其特质更像是计算式实例属性。
*/

do {

print("\n-------------2. 对下标的继承-----------------\n")

class F {
    
    var member = 1
    
    // 定义下标
    subscript(index: Int) -> Int {
        return index + member
    }
    
    // 定义下标
    subscript(str: String) -> Int {
        return str.count + member
    }
}

class C: F {
    
    /// 重写父类的下标方法
    override subscript(index: Int) -> Int {
        return index - member
    }
    
    /// 重写父类的下标方法,并且不允许子类再次重写
    override final subscript(str: String) -> Int {
        return str.count - member
    }
}

// 使用

let f: F = C()
// 调用子类的下标方法
var v = f[10]
print("v = \(v)")
// 调用子类的下标方法
v = f["abc"]
print("v = \(v)")

/*
 结果:
 
 v = 9
 v = 2
 */

/*
 结果:
 下标的重写与方法重写类似,都是在前面加上override关键字
 */

}

// 3.类的初始化器方法
/*
类的初始化器与结构体的初始化器语法上基本一样。不过呢,类的初始化器没有默认的逐成员的形式。还记得吗?
就是如果没有定义初始化器,结构体会自动生成一个逐成员的初始化器,把所有的参数包括在内的。
既然如此,那么在类中,如果有未初始化的存储类属性,就要显示的使用初始化器对它进行初始化。

注意:
由于继承关系,在初始化器中需要显示的调用父类的初始化器,使得初始化向上传递。
*/

do {

print("\n---------------3.类的初始化器方法-------------------\n")

class A {
    
    var a: Int
    
    /// 定义一个不带参数的初始化器,并且对a进行初始化
    init() {
        a = 0
    }
    
    /// 定义一个带参数的初始化器
    init(a: Int) {
       self.a = a
    }
    
    /// 定义一个便利初始化器,带一个参数
    convenience init(b: Int) {
        // 调用指定的初始化器
        self.init(a: b)
        print("这里是便利初始化器b")
    }
    
    convenience init(c: Int) {
        print("这里是便利初始化器c")
        self.init(b: c)
    }
}

// 通过不带参数的指定初始化器来创建A的实例
var a = A()
print("a1 = \(a.a)")

// 通过指定初始化器创建A的实例
a = A(a: 10)
print("a2 = \(a.a)")

// 通过便利初始化器创建A的实例
a = A(b: 20)
print("a3 = \(a.a)")

// 通过便利初始化器创建A的实例
a = A(c: 30)
print("a4 = \(a.a)")

/*
 注意:
 每个类中必须有一个指定初始化器,而便利初始化器必须调用一个初始化器,只是对初始化的属性进行一个
 过滤或者其他的操作。
 */

}

相关文章

网友评论

    本文标题:swift4.1 系统学习十八 类(二)

    本文链接:https://www.haomeiwen.com/subject/oupktqtx.html