鍍金池/ 教程/ Scala/ 組合和繼承–多態(tài)和動態(tài)綁定
包對象
Ordered Trait
組合和繼承–定義 final 成員
基本數(shù)據(jù)類型
Match 表達(dá)式
類和對象 (三)
操作基本數(shù)據(jù)類型
for 表達(dá)式
組合和繼承–重載成員函數(shù)和方法
類和對象 (二)
組合和繼承–定義 factory 對象
組合和繼承–多態(tài)和動態(tài)綁定
Trait 的基本概念
if 表達(dá)式
組合和繼承–抽象類
函數(shù)–函數(shù)字面量的一些簡化寫法
while 循環(huán)
組合和繼承–使用組合還是繼承?
訪問控制修飾符
Trait 示例–Rectangular 對象
組合和繼承–定義參數(shù)化成員變量
組合和繼承–定義無參數(shù)方法
類和對象 (一)
函數(shù)–閉包
函數(shù)–類成員函數(shù)
Scala 基本數(shù)據(jù)類型的實(shí)現(xiàn)方法
try 表達(dá)式處理異常
選擇瘦接口還是胖接口設(shè)計(jì)?
組合和繼承–小結(jié)
創(chuàng)建新的控制結(jié)構(gòu)
使用 import
為訪問控制修飾符添加作用域
Scala 的類層次關(guān)系
類和對象 (五)
傳名參數(shù)
柯里化函數(shù)
函數(shù)–頭等公民
組合和組合和繼承–定義 heighten 和 widen 函數(shù)
使用 Package–將代碼放入包中
隱含的 import
所有類的公共子類–底層類型
進(jìn)一步 Scala
函數(shù)–局部函數(shù)
引用包中的代碼
組合和繼承–使用 override 修飾符
組合和繼承–實(shí)現(xiàn)類 Element 的 above,beside 和 toString()方法
類和對象 (四)
函數(shù)–尾遞歸
沒有“break”和“continue”的日子
組合和繼承–調(diào)用基類構(gòu)造函數(shù)
減低代碼重復(fù)
函數(shù)–函數(shù)–可變參數(shù),命名參數(shù),缺省參數(shù)
起步 Scala
組合和繼承–擴(kuò)展類
函數(shù)–部分應(yīng)用的函數(shù)
開始神奇的 Scala編程之旅
組合和繼承–概述
Trait 用來實(shí)現(xiàn)可疊加的修改操作

組合和繼承–多態(tài)和動態(tài)綁定

在前面的例子我們看到類型為 Element 的變量可以保存 ArrayElement 類型的對象,這種現(xiàn)象稱為“多態(tài)”。也就是基類類型的變量可以保存其子類類型的對象,到目前為止我們定義了兩個 Element 的子類,ArrayElement 和 LineElement。你還可以定義其它子類,比如:

class UniformElement (ch :Char,
  override val width:Int,
  override val height:Int
) extends Element{
  private val line=ch.toString * width
  def contents = Array.fill(height)(line)
}

結(jié)合前面定義的類定義,我們就有了如下圖所示的類層次關(guān)系:

http://wiki.jikexueyuan.com/project/scala-development-guide/images/13.png" alt="" />

Scala 將接受所有的下列賦值,因?yàn)橘x值表達(dá)式的類型符合定義的變量類型:

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)

若你檢查繼承層次關(guān)系,你會發(fā)現(xiàn)這四個 val 定義的每一個表達(dá)式,等號右側(cè)表達(dá)式的類型都在將被初始化的等號左側(cè)的 val 類型的層次之下。

另一方面,如果調(diào)用變量(對象)的方法或成員變量,這個過程是一個動態(tài)綁定的過程,也就是說調(diào)用哪個類型的方法取決于運(yùn)行時變量當(dāng)前的類型,而不是定義變量的類型。

為了顯示這種行為,我們在 Element 中添加一個 demo 方法,定義如下:

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

如果你使用交互式 Scala 解釋器來測試,你可以定義如下的方法:

def invokeDemo(e: Element) { 
  e.demo() 
}

下面我們分別使用 ArrayElement,LineElement 和 UniformElement 來調(diào)用這個方法:

scala> invokeDemo(new ArrayElement)
ArrayElement's implementation invoked
scala> invokeDemo(new LineElement)
LineElement's implementation invoked
scala> invokeDemo(new UniformElement)
Element's implementation invoked

可以看到由于 ArrayElement 和 LineElement 重載了 Element 的 demo 方法,因此調(diào)用 invokeDemo 時由于“動態(tài)綁定”因此會調(diào)用這些子類的 demo 方法,而由于 UniformElement 沒有重載 Element 的 demo 方法,動態(tài)綁定時也會調(diào)用 UniformElement 的 demo 方法(但此時實(shí)際為基類的 demo 方法)。