出處:程式設計基本功與實務一書
抽象類別
當只想定義子類別的共同部分時,但要求該類別不能有實體;或者提供某方法,並確保子類別提供該方法特定的實作;此時就可利用C#的abstract修飾詞,運用類別和方法,形成
抽象類別與抽象方法。
抽象類別只能當作其他類別的父類別,用來定義一些子類別的共同部分、被其他類別所繼承,且不能用new運算子來實體化,但可以用來宣告物件變數。
例如:形狀是一個共通的抽象概念,應該要定義為抽象類別shape;而三角形和矩形才是具體的形狀。
抽象方法只允許在抽象類別中,即一個有抽象方法的類別,就必須要是抽象類別。抽象方法宣告沒有實際的實作,因此沒有方法主體
|
圖形管理介面 |
|
按下圖形管理介面的新增三角形後跳出的視窗 |
|
按下圖形管理介面的新增矩形後跳出的視窗 |
圖形集合以及處理該集合的相關功能封裝在 類別ShapeCollection中:
描述圖形集合的表示方式,以及處理該集合相關功能;假設以物件陣列的方式來表示「圖形集合」,陣列名稱為shapeArray,並以count紀錄目前陣列有多少個圖形。
為達到封裝目的,這兩個資料成員都宣告為private (即count & shapeArray)
而此類別宣告public方法getCount()讓外界知道目前的圖形數量和
add方法讓使用者可以將圖形加入集合中;
另一個方法則listing則是讓使用者以字串方式取得圖形集合中每一圖形的資訊。
ShapeCollection 類別:
class ShapeCollection
{
private int count = 0;
private Shape[] shapeArray = new Shape[100];
public ShapeCollection() {
}
public int getCount() { return count; }
public void add(Shape s)//加進陣列shapeArray中
{
if (s != null && count
< 100)
shapeArray[count++] = s;
}
public string listing()
{
string res = "";
for (int i = 0; i <
count; i++)
{
//
polymorphism
Shape s = shapeArray[i];
res += s.show() + ", 面積
= " +
s.area() +
"\r\n-----------------------\r\n";
}
return res;
}
/*
* 使用interface Comparable的compareTo(Object obj)方法取得比較的結果
*/
public string maxShape()
{
if (count == 0) return "尚未有圖形";
string res = "";
Shape max =
shapeArray[0];
for (int i = 1; i <
count; i++)
{
Shape cObj =
shapeArray[i];
if (((Comparable)cObj).compareTo(max)
> 0)
max = cObj;
}
res = max.show();
return res;
}
public string rankShape()
{
string res = "[ ";
if (count == 0) return res + "]";
int[] rank = new int[count];
for (int i = 0; i <
count; i++)
{
rank[i] = 1;
Shape iShape =
shapeArray[i];
for (int j = 0; j <
count; j++)
{
Shape jShape =
shapeArray[j];
if (((Comparable)jShape).compareTo(iShape)
> 0)
rank[i]++;
}
}
for (int i = 0; i <
count; i++)
res += rank[i] + " ";
return res + "]";
}
}
主程式:
public partial class ShapeManagerForm : Form
{
public ShapeManagerForm()
{
InitializeComponent();
}
private void btnExit_Click(object sender, EventArgs e)
{
Close();
}
ShapeCollection ShapeManager = new ShapeCollection();
//new一個ShapeCollection類別叫做ShapeManager。
//這樣的做法可以讓很多個物件用這個類別。
private void
ShapeManagerForm_Load(object sender, EventArgs e)
{
lblCounter.Text = "目前共有" + ShapeManager.getCount() + "個圖形";
}// 透過ShapeManager來執行其類別底下的方法getCount()
private void btnTriangle_Click(object sender, EventArgs e) //新增三角形
{
TriangleForm tForm = new TriangleForm();//表單切換的方式
if (tForm.ShowDialog()
== DialogResult.OK)
{
ShapeManager.add(tForm.tObj);
txtOutput.Text = "新增三角形\r\n" + tForm.tObj.show() + "\r\n";
lblCounter.Text = "目前共有" + ShapeManager.getCount() + "個圖形";
}
tForm.Dispose();
}
private void btnRectangle_Click(object sender, EventArgs e) //新增矩形
{
RectangleForm rForm = new RectangleForm();
if (rForm.ShowDialog()
== DialogResult.OK)
{
ShapeManager.add(rForm.rObj);
txtOutput.Text = "新增矩形\r\n" + rForm.rObj.show() + "\r\n";
lblCounter.Text = "目前共有" + ShapeManager.getCount() + "個圖形";
}
rForm.Dispose();
}
private void btnListing_Click(object sender, EventArgs e)//列出所有圖形
{
string str = "<<< 列出所有圖形 >>>\r\n";
str += ShapeManager.listing();
txtOutput.Text = str;
}
private void btnCompare_Click(object sender, EventArgs e)//圖形比較
{
string str = "<<< 圖形比較 >>>\r\n";
str += ShapeManager.listing();
str += "圖形次序: " + ShapeManager.rankShape();
str += "\r\n最大圖形: " + ShapeManager.maxShape();
txtOutput.Text = str;
}
}
三角形Form表單:
public partial class TriangleForm : Form
{
public TriangleForm()
{
InitializeComponent();
}
internal Triangle tObj;
//為了讓主選單可以取得此新建立的Triangle物件,所以宣告一個internal物件變數tObj來參考此物件,則此時同一專案中的城市都可以存取變數tObj來參考此物件
private void btnOK_Click(object sender, EventArgs e)
{
double tbase = Convert.ToDouble(txtBase.Text);
double height = Convert.ToDouble(txtHeight.Text);
tObj = new Triangle(tbase, height);
}
}
矩形Form表單:
public partial class RectangleForm : Form
{
public RectangleForm()
{
InitializeComponent();
}
internal Rectangle rObj;
//為了讓主選單可以取得此新建立的Rectangle物件,所以宣告一個internal物件變數rObj來參考此物件,則此時同一專案中的城市都可以存取變數rObj來參考此物件
private void btnOK_Click(object sender, EventArgs e)
{
double width = Convert.ToDouble(txtWidth.Text);
double height = Convert.ToDouble(txtHeight.Text);
rObj = new Rectangle(width, height);
}
private void RectangleForm_Load(object sender, EventArgs e)
{
}
}
介面
在繼承架構中,利用「介面」為類別加掛特定的類別行為。
程式用interface關鍵字定義介面,在介面內中宣告的方法
自動屬於公開的抽象方法,
故介面和抽象類別一樣都不能被實體化,但可用來宣告物件變數。
註:在物件導向裡, Interface 最大的功能是提供物件的多重類型.
因為物件跟物件本身是沒有辦法多重繼承. 所以利用介面可以達到這個目的
問答題:
1.請問甚麼是抽象類別和抽象方法?請舉例說明抽象類別和抽象方法的用途和運作原理?
2.甚麼是介面?請舉例說明其用途和運作原理
3.請說明類別繼承、介面實作、方法覆寫和型態轉換在多型機制運作上的關係
留言