2016-04-27 09:17:52 qq_25491201 阅读数 1224

swift面向对象之多态与继承

1.多态



运行时多态

运行时多态的要点

1.要有继承关系的存在

2.子类要重写父类的方法

3.父类类型的引用指向子类实例

2.继承


1.继承的注意

继承可以用于类而不能用于结构体和枚举,继承也可用于协议

swift中不能使用多继承,oc中也是


父类的计算属性可以被子类所重写,如果该计算属性在父类中是只读的,则子类可以重写该属性使其成为只读或可读可写属性,但是如果属性在父类中是可读可写属性那么在子类重写后必须是可读可写属性而不能是只读属性,因为子类属性的读写权限必须大于或等于父类


2.Super的使用

super的使用可以调用父类的方法,不过只有拥有父类的类才可以使用super

在子类的实例方法中使用super,super代表子类实例中用父类类型初始化的部分,而在子类的类型方法中调用super时,super表示父类的类型本身


3.拒绝子类重写

final这个关键字可以防止父类中的方法或属性被之类给改写,如果改写就出错


2018-03-26 17:31:00 weixin_43172830 阅读数 61

前言

  • 同样的操作或者方法,不同的对象在执行时会出现完全不同的行为,这就叫多态。

1、Swift 多态

  • 多态是讲具有同样的父类的一批类之间,都重写了父类的同一个方法实现自己的行为,但是表现出来则各不相同。

    • 多态属于一种叫模板模式的设计模式。

2、多态与重载的区别

  • 多态是针对不同对象调用同一个方法,能产生不一样的结果。

  • 重载是在同一个类内实现了多个同名的方法,重载针对同一个对象,同名的方法,参数不同,调用后结果相同不相同不关心。

2019-07-13 19:10:27 weixin_42433480 阅读数 35

多态:父类指针指向子类对象

多态的实现原理:

OC: Runtime

C++: 虚表(虚函数表)

Swift:类似于虚表

多态代码:

class Animal {
    func speak() {
        print("Animal speak")
    }
    func eat() {
        print("Animal eat")
    }
    func sleep() {
        print("Animal sleep")
    }
}

class Dog: Animal {
    override func speak() {
        print("Dog speak")
    }
    override func eat() {
        print("Dog eat")
    }
}

var anim: Animal
anim = Animal()
anim.speak()
anim.eat()
anim.sleep()

anim = Dog()
anim.speak()
anim.eat()
anim.sleep()

输出结果:

 


对比结构体和类对方法的调用

  • 结构体代码:
struct Animal {
   func speak() {
    print("Animal speak")
  }
   func eat() {
    print("Animal eat")
  }
   func sleep() {
    print("Animal sleep")
  }
}

var anim = Animal()
anim.speak()
anim.eat()
anim.sleep()

结构体的反汇编代码:

由上图可以看出,结构体的函数的地址在调用时一开始就固定的也就是一编译完就能确定调用哪个函数,这是因为结构体不存在继承,可以直接确定

  • 类代码:
class Animal {
    func speak() {
        print("Animal speak")
    }
    func eat() {
        print("Animal eat")
    }
    func sleep() {
        print("Animal sleep")
    }
}

var anim = Animal()
anim.speak()
anim.eat()
anim.sleep()

类的反汇编代码:

上图以此为speak,eat,sleep方法的反汇编代码,我们可以看出,它们的地址是不固定的,这是因为类存在继承特性,需要运行时才能确定真正调用哪个方法


多态实现原理

  • 多态代码
class Animal {
    func speak() {
        print("Animal speak")
    }
    func eat() {
        print("Animal eat")
    }
    func sleep() {
        print("Animal sleep")
    }
}

class Dog: Animal {
    override func speak() {
        print("Dog speak")
    }
    override func eat() {
        print("Dog eat")
    }
    func run() {
        print("Dog run")
    }
}

var anim = Animal()
anim.speak()
anim.eat()
anim.sleep()

anim = Dog()
anim.speak()
anim.eat()
anim.sleep()
  • 多态部分反汇编代码

1中是从全局变量anim的取出8个字节给rax,rax里也就是堆空间Dog对象的地址值

2中是从堆空间里取出8个字节给rcx,rcx里存储的就是Dog对象堆空间内存的前八个字节,也就是类型信息(存储着类的相关信息,包括里面的方法等)。

3就是找到存储类型信息的内存地址,加上方法的偏移量,就可以找到对应要调用的方法

图解:

注意:两个不同的Dog对象前8个字节相同,因为它存储着共同的一样的类型信息,而且类型信息存储在全局区

 

 

 

2019-03-24 20:09:29 qq_36487644 阅读数 65

1.静态多态

静态多态就是在系统编译期间就可以确定程序执行到这里将要执行哪个函数,比如函数的重载。

2.动态多态

动态多态是利用虚函数实现了运行时的多态,也就是说在系统编译的时候并不知道程序将要调用哪一个函数,只有在运行到这里的时候才能确定接下来会跳转到哪一个函数的栈帧。

虚函数就是在基类中声明该函数是虚拟的(在函数之前加virtual关键字),然后在子类中正式的定义(子类中的该函数的函数名,返回值,函数参数个数,参数类型,全都与基类的所声明的虚函数相同,此时才能称为重写,才符合虚函数,否则就是函数的重载),再定义一个指向基类对象的指针,然后使该指针指向由该基类派生的子类对象,再然后用这个指针来调用改虚函数,就能实现动态多态。

2016-12-18 13:47:09 kavenGw 阅读数 366

继承

swift的继承是单一继承。

    class className : superClass{}

多态

方法多态

    class baseClass{
        func move(){}
    }
    class superClasS{
        override func move(){}
    }

属性多态
通过继承属性 你可以改变 get和set

    class baseClass{
        var age : Int{
            get {return 4}
        }
    }
    class superClass{
        override var age : Int{
            get {return 7}
        }
    }

禁止多态

    //将整个类标识为禁止继承
    final class className{}
    //将类的部分成员变量或者函数禁止继承
    class className{
        final func methodName
    }

扩展

    *类似于C# partial在不添加新的类的情况下来扩展原有的类*

    extension className{}

但是扩展有功能限制:

  1. 添加计算型属性和计算型静态属性

    extension Int{
        var sub : Int {return self - 10}
    }
    
  2. 定义实例方法和类型方法

    extension Int{
        var say(){
            return "A"  
        } 
    }
    
  3. 提供新的构造器

    stuct mult{
        var _x = 1
    }
    extension mult{
        init(x:Int){
            _x  = x
        }
    }
    
  4. 定义下标

    extension Int{
        subscript(var multtable : Int) -> Int{
            var no1 = 1
            while multtable > 0{
                no1 *= 10
                --multtable
            }
            return (self / no1) % 10
        }
    }
    
  5. 嵌套类型

    extension Int{
        enum calc{
            case add
            case sub
        }
    }
    
  6. 可变实例方法

    extension Double{
        mutating func square(){
            return self * self
        }
    }
    

协议

协议只定义变量名和方法名而不需要实现.

    protocal protacolName{
        var property1 : datatype{get}
        var property2 : datatype{get set}
        func methodName(parameters) -> datatype
    }


协议中所有的变量和方法必须在继承的类中实现

    protocol test{
        var cash : Int{get}
        func purchase(price : Int) -> String
    }

    class Shopper : test{
        var cash : Int
        func purchase(price : Int) -> String{
            cash -= price
            return "OK"
        }
    }

可选协议
定义可选变量和方法

    @objc protocol protocolName{
        var requiredProperty : dataType
        optional var optionalProperty : dataType
    }

    class className : protocalName{
        @objc var requiredProperty : dataType = initialValue
        var requiredProperty : dataType = initialValue
    }

协议继承

不同于类的继承是单一的,一个协议可以继承多个接口

    protocal first{}
    protocal seconde{}
    protocal third : first,second{}

协议扩展

protocal cat{}
extension cat{}

//协议选择性扩展
extension Cat where self:Black{}
没有更多推荐了,返回首页