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

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.

主站蜘蛛池模板: 商丘市| 吉木萨尔县| 渑池县| 舞钢市| 疏勒县| 恩平市| 洛南县| 陈巴尔虎旗| 晴隆县| 文成县| 江口县| 大城县| 尚义县| 昌图县| 垣曲县| 米泉市| 兴安县| 太仓市| 丹寨县| 靖西县| 喀喇沁旗| 大姚县| 临颍县| 娱乐| 利川市| 沙河市| 玛多县| 庐江县| 张掖市| 霞浦县| 天峨县| 苗栗市| 宁阳县| 墨玉县| 青冈县| 安福县| 博客| 江都市| 兰考县| 尖扎县| 岳普湖县|