폴킴 (Paul Kim) -你都記得 You Remember

曾經有那樣深刻的感情,因為家裡反對和當時自己的懦弱 在那之後幾乎看到廟宇就許下:願把自己下半輩子的幸福都給你,只願你幸福喜樂 所以看到這段歌詞非常有感,年紀即將過40,所以真的得若無其事地活下去  네가 아주 행복했음 좋겠어 要是你過得幸福就好了 대신 내가 불행하면 좋겠어 要是換成我變得不幸就好了 기억나지 않았으면 좋겠어 如果什麼都不記得就好了 다시 돌아갈 수 있음 좋겠어 如果能夠再次回頭就好了 너의 찰나와 영원들이 願你所有的剎那和永恆 너만의 것이 되길 都變成專屬於你自己的時刻 사실 난 행복을 잘 몰라 但其實我真的不懂所謂的幸福是什麼 너는 아무렇지 않게 살아가야 하니까 因為你得若無其事地活下去

抽象類別和介面


出處:程式設計基本功與實務一書

抽象類別

當只想定義子類別的共同部分時,但要求該類別不能有實體;或者提供某方法,並確保子類別提供該方法特定的實作;此時就可利用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 ComparablecompareTo(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.請說明類別繼承、介面實作、方法覆寫和型態轉換在多型機制運作上的關係

留言

這個網誌中的熱門文章

C# 裡 List用法

"需要有物件參考才能使用非靜態欄位、方法或屬性"的問題排除

達因筆 & 表面能 原理