官术网_书友最值得收藏!

Overriding member extension functions

Member extension functions can be declared as open if you wish to allow them to be overridden in subclasses. In this case, the dispatcher receiver type will be virtual; that is, it will be the runtime instance. However, the extension receiver will always be resolved statically.

To demonstrate this, we will create a class called Element, which has a function called react. This function will accept a Particle type:

open class Particle
class Electron : Particle()

open class Element(val name: String) {

fun react(particle: Particle) {
particle.doReaction(name)
}

open fun Particle.doReaction(name: String) {
println("$name is reacting with a particle")
}

open fun Electron.doReaction(name: String) {
println("$name is reacting with an electron to make an isotope")
}
}

You can see that we have two particles – a superclass and a subclass called Electron. When we call the react function, it just delegates to a member extension function called doReaction. Now, let's use this class as follows:

val selenium = Element("Selenium")
selenium.react(Particle())
selenium.react(Electron())

Creating the element and calling react with both a Particle type and an Element class results in the following:

Selenium is reacting with a particle
Selenium is reacting with a particle

As you can see, the extension function defined on Particle was invoked in both cases, even though, at runtime, one of the inputs was an Electron instance. This is because the extension type of a member extension function is always determined at compile time, and at compile time, the type is Particle.

Now, if we extend Element with a subclass called NobleGas, and then add another react method to accept an Electron subclass instead, we have the following:

class NobleGas(name: String) : Element(name) {

override fun Particle.doReaction(name: String) {
println("$name is noble, it doesn't react with particles")
}

override fun Electron.doReaction(name: String) {
println("$name is noble, it doesn't react with electrons")
}

fun react(particle: Electron) {
particle.doReaction(name)
}
}

To be clear, the react method in this subclass is in addition to the react method inherited from the parent class. The subclass has two functions available, one that accepts any Particle type, and one that specifically accepts an Electron type.

If we now run the following code:

val helium = NobleGas("Helium")
helium.react(Particle())
helium.react(Electron())

The output of this function will differ from the previous example as follows:

Helium is noble, it doesn't react with particles
Helium is noble, it doesn't react with electrons

We have seen in this case that the more specific method is invoked. This is because, at runtime, the more specific react function will be invoked – the one added in the subclass. And, since this function declared the input type to be Electron, the extension function determined at compile time was the extension function defined on the Electron type.

主站蜘蛛池模板: 即墨市| 龙游县| 惠州市| 台前县| 太仓市| 盐津县| 合阳县| 西充县| 庆元县| 东宁县| 若羌县| 久治县| 中宁县| 临高县| 嵩明县| 新密市| 长丰县| 阜新市| 民乐县| 夏津县| 中方县| 新和县| 通江县| 绩溪县| 云阳县| 伊金霍洛旗| 桦甸市| 黔南| 阳江市| 聂荣县| 神池县| 枣庄市| 吉木乃县| 平遥县| 闸北区| 阿勒泰市| 建德市| 都匀市| 尖扎县| 三台县| 平乐县|