《多態性》

《多態性》

多態性是指同一操作作用於不同的類的實例、不同的類將進行不同的解釋、最後產生不同的執行結果。C#支持兩種類型的多態性:編譯時的多態性(靜態聯編),運行時的多態性(動態聯編)。

【說明】:此教學設計任務由南京曉莊學院現代教育技術課程老師yqiong參與教師-維基星光計畫進行wiki教學而發布。此詞條為範例詞條,由大蝦選定主題並負責、參與現代教育技術課程的所有同學協作共同完成!

基本信息

科目:信息技術 教學對象:大學一年級
課時:2教學環境:計算機網路教室

學習者特徵分析

上一章的學習中,學生已經經歷了利用計算機解決問題的基本過程,領略了用計算機解題的奇妙之道,感悟了程式設計是其中的關鍵環節,對程式設計已經產生一定興趣,但由於在程式設計過程中,涉及數學、英語學科知識點較多,學生還沒有足夠的相關知識儲備且我校學生基礎薄弱,這樣主、客觀兩方面的因素造成在進行下一環節教學,會存在一定困難,難以深入開展下去。

教學內容

定義

在C#中多態性的定義是:同一操作作用於不同的類的實例、不同的類將進行不同的解釋、最後產生不同的執行結果。
C#支持兩種類型的多態性:

編譯時的多態性(靜態聯編)

編譯時的多態性是通過重載來實現的。方法重載和操作符重載、它們都實現了編譯時的多態性。
對於非虛的成員來說系統在編譯時根據傳遞的參數、返回的類型等信息決定實現何種操作。

運行時的多態性(動態聯編)

運行時的多態性就是指直到系統運行時才根據實際情況決定實現何種操作C#中運行時的多態性。
通過虛成員實現。
編譯時的多態性為我們提供了運行速度快的特點而運行時的多態性則帶來了高度靈活和抽象的特點。

虛方法

當類中的方法聲明前加上了virtual 修飾符,我們稱之為虛方法,反之為非虛。
使用了virtual 修飾符後不允許再有static, abstract, 或 override 修飾符。

對於非虛的方法,無論被其所在類的實例調用還是被這個類的派生類的實例調用,方法的執行方式不變。而對於虛方法它的執行方式可以被派生類改變,這種改變是通過方法的重載來實現的。

實例

靜態多態性指的是程式在編譯時,系統就能決定調用哪個函式,如重載。
動態多態性指在運行中才能動態確定操作指針所指的對象,主要通過虛函式和重寫來實現。
java 的多態機制遵循一個原則:當父類對象引用變數引用子類對象時,被引用對象的類型而不是引用變數的類型決定了調用誰的成員方法,但是這個被調用的方法必須是在超類中定義過的,也就是說被子類覆蓋的方法
概念理解起來有點抽象。還是看個例子吧。
靜態多態性:
add(int a);
add(int a,int b);
add(double a);
add(double a,double b);
動態多態性
public class A{ }
public class AB extends A{ }
public class AC extends A{ }
public class test{
go(A a);

教學重點及難點

下面的例子說明了虛方法與非虛方法的區別:

程式清單
Code highlighting produced by Actipro CodeHighlighter (Freeware)
http://www.CodeHighlighter.com/
-->using System;
class A
{
public void F() { Console.WriteLine("A.F"); }
public virtual void G() { Console.WriteLine("A.G"); }
}
class B: A
{
new public void F() { Console.WriteLine("B.F"); }
public override void G() { Console.WriteLine("B.G"); }
}
class Test
{
static void Main() {
B b = new B();
A a = b;
a.F();
b.F();
a.G();
b.G();
}
}
例子中A 類提供了兩個方法,非虛的F 和虛方法G 。類B 則提供了一個新的非虛的方法F,
從而覆蓋了繼承的F 。類B 同時還重載了繼承的方法G。 那么輸出應該是
Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/
-->A.F
B.F
B.G
B.G
注意到本例中方法a.G() 實際調用了B.G 而不是A.G ,這是因為編譯時值為A,但運行時值為B。
所以B 完成了對方法的實際調用。
在派生類中對虛方法進行重載
先讓我們回顧一下普通的方法重載。
普通的方法重載指的是類中兩個以上的方法,包括隱藏的繼承而來的方法,取的名字相同,只要使用的參數類型或者參數個數不同,編譯器便知道在何種情況下應該調用哪個方法。
而對基類虛方法的重載是函式重載的另一種特殊形式。
在派生類中重新定義此虛函式時要求的是方法名稱,返回值類型,參數表中的參數個數,類型,順序都必須與基類中的虛函式完全一致。在派生類中聲明對虛方法的重載要求在聲明中加上override 關鍵字,而且不能有new, static 或virtual 修飾符。
我們用汽車類的例子來說明多態性的實現
程式清單:
Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/
-->using System;
class Vehicle//定義汽車類
{
public int wheels; //公有成員輪子個數
protected float weight; //保護成員重量
public Vehicle(int w,float g){
wheels = w;
weight = g;
}
public virtual void Speak(){
Console.WriteLine("the w vehicle is speaking!");
}
};
class Car:Vehicle //定義轎車類
{
int passengers; //私有成員乘客數
public Car(int w,float g,int p) : base(w,g)
{
wheels = w;
weight = g;
passengers = p;
}
public override void Speak(){
Console.WriteLine("The car is speaking:Di-di!");
}
}
class Truck:Vehicle //定義卡車類
{
int passengers; //私有成員乘客數
float load; //私有成員載重量
public Truck (int w,float g,int p float l) : base(w,g)
{
wheels = w;
weight = g;
passengers = p;
load = l;
}
public override void Speak(){
Console.WriteLine("The truck is speaking:Ba-ba!");
}
}
class Test
{
public static void Main(){
Vehicle v1 = new Vehicle();
Car c1 = new Car(4,2,5);
Truck t1 = new Truck(6,5,3,10);
v1.Speak();
v1 = c1;
v1.Speak();
c1.Speak();
v1 = t1;
v1.Speak();
t1.Speak();
}
}
分析上面的例子我們看到
z Vehicle 類中的Speak 方法被聲明為虛方法,那么在派生類中就可以重新定義此方法;
z 在派生類Car 和Truck 中分別重載了Speak 方法。派生類中的方法原型和基類中的方法原型必須完全一致;
z 在Test 類中創建了Vehicle 類的實例v1 ,並且先後指向Car 類的實例c1 和Truck 類的實例t1。
運行該程式結果應該是
Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/
-->The Vehicle is speaking!
The car is speaking:Di-di!
The car is speaking:Di-di!
The truck is speaking:Ba-ba!
The truck is speaking:Ba-ba!
這裡Vehicle 類的實例v1 先後被賦予Car 類的實例c1 以及Truck 類的實例t1的值。
在執行過程中,v1 先後指代不同的類的實例從而調用不同的版本。
這裡v1 的Speak 方法實現了多態性,並且v1.Speak 究竟執行哪個版本不是在程式編譯時確定的
而是在程式的動態運行時根據v1 某一時刻的指代類型來確定的,所以還體現了動態的多態性。
Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/
-->exercise:求輸入結果。
public class A
{
public virtual void Fun1(int i)
{
Console.WriteLine(i);
}
public void Fun2(A a)
{
a.Fun1(1);
Fun1(5);
}
}
public class B : A
{
public override void Fun1(int i)
{
base.Fun1 (i + 1);
}
public static void Main()
{
B b = new B();
A a = new A();
a.Fun2(b);
b.Fun2(a);
}
}
Answer:
/*
2
5
1
6

*/

教學策略

本節課主要採用了講授法小組合作式,自主探究學習方法,任務驅動法,強化練習法,交流討論法等。
從學生日常生活問題入手,快速自然的引導學生走進主題,明確本節課的學習目標,引發學生積極思考;講授新課內容,以醒目的方式將多態性的定義和分類及實例呈現給學生;以小組合作的方式,在討論與探究中完成任務;把滑鼠還給學生,自己動手實踐,課程安排形成循序漸進的梯度,充分挖掘學生潛力。通過課後練習鞏固學生對知識的掌握。

相關詞條

相關搜尋

熱門詞條

聯絡我們