Scala程序中如何实现多态和动态绑定
在10.4节中你看到了类型Element的变量可以指向类型ArrayElement的对象。这种现象的名字叫多态:polymorphism,是指“许多形状”或“许多形式”的意思。这种情况下,Element对象可以有许多形式。这种类型的多态被称为子类型化多态:subtyping polymorphism。Scala里另一种类型的多态,称为统一多态:universal polymorphism,将在第19章讨论。目前为止,你已经看到了两种形式:ArrayElement和LineElement。你可以通过定义新的Element子类创造Element的更多形式。例如,下面定义了拥有给定长度和高度并被指定字符充满的新的Element形式:
class UniformElement(
ch: Char,
override val width: Int,
override val height: Int
) extends Element {
private val line = ch.toString * width
def contents = Array.make(height, line)
} 
图释 10.3 布局元素的类层级
51CTO编辑推荐:Scala编程语言专题
类Element的继承层级现在看上去如图释10.3展示的样子。结果,Scala将接受所有的下列赋值,因为赋值表达式的类型符合定义的变量类型:
val e1: Element = new ArrayElement(Array("hello", "world"))
val ae: ArrayElement = new LineElement("hello")
val e2: Element = ae
val e3: Element = new UniformElement('x', 2, 3) 若你检查继承层级,你会发现这四个val定义的每一个里,等号右侧表达式的类型都在将被初始化的等号左侧的val类型之下。 然而,另一半的故事是,变量和表达式上的方法调用是动态绑定:dynamically bound的。这意味着被调用的实际方法实现取决于运行期对象基于的类,而不是变量或表达式的类型。为了演示这种行为,我们会从我们的Element类中临时移除所有存在的成员并添加一个名为demo的方法。我们会在ArrayElement和LineElement中重载demo,但UniformElement除外:
abstract class Element {
def demo() {
println("Element's implementation invoked")
}
}
class ArrayElement extends Element {
override def demo() {
println("ArrayElement's implementation invoked")
}
}
class LineElement extends ArrayElement {
override def demo() {
println("LineElement's implementation invoked")
}
}
// UniformElement inherits Element’s demo
class UniformElement extends Element 如果你把这些代码输入到了解释器中,那么你就能定义这个带了一个Element并调用demo的方法: def invokeDemo(e: Element) {
e.demo()
} 如果你传给invokeDemo一个ArrayElement,你会看到一条消息指明ArrayElement的demo实现被调用,尽管被调用demo的变量e的类型是Element: scala> invokeDemo(new ArrayElement) ArrayElement's implementation invoked相同的,如果你传递LineElement给invokeDemo,你会看到一条指明LineElement的demo实现被调用的消息:
scala> invokeDemo(new LineElement) LineElement's implementation invoked传递UniformElement时的行为一眼看上去会有些可以,但是正确:
scala> invokeDemo(new UniformElement) Element's implementation invoked
相关推荐
lynjay 2020-06-06
jameszgw 2020-06-03
Greatemperor 2020-05-17
HongKongPython 2020-05-12
宿舍 2020-05-06
Darklovy 2020-04-29
austindev 2020-04-25
sunnyJam 2020-04-15
fly00love 2020-03-08
ladysosoli 2020-03-01
llwang0 2020-02-29
TreasureZ 2020-02-22
jacktangj 2020-02-19
明天你好 2020-02-18
katyusha 2020-02-16
wangqing 2020-02-13
vanturman 2020-02-10
Winterto0 2020-01-28