(二十四)swift 类的重写(Overriding)

/*


子类可以为继承来的实例方法(instance method),类方法(class method),实例属性(instance propert y),或下标脚本(subscript)提供自己定制的实现(implementation)。我们把这种行为叫重写(overridin g)




如果要重写某个特性,你需要在重写定义的前面加上  override 关键字。这么做,你就表明了你是想提供一个重写版本,而非错误地提供了一个相同的定义。意外的重写行为可能会导致不可预知的错误,任何缺少  关键 字的重写都会在编译时被诊断为错误。

override关键字会提醒 Swift编译器去检查该类的超类(或其中一个父类)是否有匹配重写版本的声明。这个检查可以确保你的重写定义是正确的。

 

 访问超类的方法,属性及下标脚本

 当你在子类中重写超类的方法,属性或下标脚本时,有时在你的重写版本中使用已经存在的超类实现会大有裨

 益。比如,你可以优化已有实现的行为,或在一个继承来的变量中存储一个修改过的值。

 在合适的地方,你可以通过使用 super前缀来访问超类版本的方法,属性或下标脚本:

 • 在方法 someMethod的重写实现中,可以通过 super.someMethod()来调用超类版本的 someMethod方法。

 • 在属性 someProperty getter setter 的重写实现中,可以通过 super.someProperty来访问超类版本的 someProperty属性。

 • 在下标脚本的重写实现中,可以通过 super[someIndex]来访问超类版本中的相同下标脚本。

 

 

 

 

 

 */



//重写方法

//在子类中,你可以重写继承来的实例方法或类方法,提供一个定制或替代的方法实现。

//下面的例子定义了 Vehicle的一个新的子类, Train ,它重写了从 Vehicle类继承来的 makeNoise方法:



class Vehicle {

    var currentSpeed = 0.0

    var description: String {

        return"traveling at\(currentSpeed) miles per hour"

    }

    func makeNoise() {

        // 什么也不做-因为车辆不一定会有噪音

    }

}



class Train: Vehicle {

    override func makeNoise() {

        print("Choo Choo")

    }

}




//如果你创建一个 Train的新实例,并调用了它的 makeNoise方法,你就会发现 Train版本的方法被调用:




let train = Train()

train.makeNoise()

// prints "Choo Choo"





//重写属性


/*

 你可以重写继承来的实例属性或类属性,提供自己定制的gettersetter,或添加属性观察器使重写的属性可以观察属性值什么时候发生改变。

 重写属性的GettersSetters

 你可以提供定制的 getter( setter)来重写任意继承来的属性,无论继承来的属性是存储型的还是计算型的属性。子类并不知道继承来的属性是存储型的还是计算型的,它只知道继承来的属性会有一个名字和类型。你在重写一个属性时,必需将它的名字和类型都写出来。这样才能使编译器去检查你重写的属性是与超类中同名同类型的属性相匹配的。

 

 你可以将一个继承来的只读属性重写为一个读写属性,只需要你在重写版本的属性里提供 getter setter 可。但是,你不可以将一个继承来的读写属性重写为一个只读属性。

 

 */



//以下的例子定义了一个新类, Car ,它是 Vehicle的子类。这个类引入了一个新的存储型属性叫做 gear ,认为整数1 Car类重写了继承自 Vehicle description属性,提供自定义的,包含当前档位的描述:



class Car: Vehicle {

    var gear = 1

    override var description:String {

        returnsuper.description +" in gear \(gear)"

    }

}






//重写的 description属性,首先要调用 super.description返回 Vehicle 类的 description属性。之后, Car 版本的 description在末尾增加了一些额外的文本来提供关于当前档位的信息。

//如果你创建了 Car 的实例并且设置了它的 gear currentSpeed 属性,你可以看到它的 description返回了 Car中定义的 description :



let car = Car()

car.currentSpeed =25.0

car.gear = 3

print("Car:\(car.description)")

// Car: traveling at 25.0 miles per hour in gear 3



//重写属性观察器(Property Observer) 

//你可以在属性重写中为一个继承来的属性添加属性观察器。这样一来,当继承来的属性值发生改变时,你就会被通知到,无论那个属性原本是如何实现的。




//注意:你不可以为继承来的常量存储型属性或继承来的只读计算型属性添加属性观察器。这些属性的值是不可以被设置,所以,为它们提供 willSet didSet 实现是不恰当。此外还要注意,你不可以同时提供重写的 setter重写的属性观察器。如果你想观察属性值的变化,并且你已经为那个属性提供了定制的 setter,那么你在 setter中就可以观察到任何值变化了。



//下面的例子定义了一个新类叫 AutomaticCar ,它是 Car的子类。 AutomaticCar 表示自动挡汽车,它可以根据当前的速度自动选择合适的挡位:


class AutomaticCar: Car {

    override var currentSpeed:Double {

        

        didSet {

            gear = Int(currentSpeed / 10.0) + 1

        }

    }

}



//当你设置 AutomaticCar currentSpeed属性,属性的 didSet观察器就会自动地设置 gear属性,为新的速度选择一个合适的挡位。具体来说就是,属性观察器将新的速度值除以10,然后向下取得最接近的整数值,最后加1得到档位 gear 的值。例如,速度为10.0,挡位为1;速度为35.0,挡位为4:



let automatic = AutomaticCar()

automatic.currentSpeed =35.0

print("AutomaticCar:\(automatic.description)")

// AutomaticCar: traveling at 35.0 miles per hour in gear 4





/*-----------------------防止重写------------------------*/


/*

 

 

 你可以通过把方法,属性或下标脚本标记为 final来防止它们被重写,只需要在声明关键字前加上 final特性即

 可。(例如: final var , final func , final class func ,以及 final subscript )

 如果你重写了 final方法,属性或下标脚本,在编译时会报错。在类扩展中的方法,属性或下标脚本也可以在扩

 展的定义里标记为 final

 你可以通过在关键字 class前添加 final特性( final class )来将整个类标记为 final,这样的类是不可被继承的,任何子类试图继承此类时,在编译时会报错。

 

 

 */


你可能感兴趣的:(继承,Class)