C#之淺析物件導向程式設計思想(二)

暫7師師長常乃超發表於2015-03-07

<pre name="code" class="csharp">//My concern is my chief concern.

    俗話說:“龍生龍鳳生鳳,老鼠的兒子會打洞”,可見在生活中,這種物件導向的思想(既“繼承”)已經深入人心,這篇部落格,就主要針對“繼承”這個概念做稍微深入一點的總結。

一、 繼承的實現

     所謂的繼承:即派生類對基類的特性進行共享以及具體化。看程式碼:

    (一)、常規繼承

namespace JiCheng
{
    public class Baseclass
    {
        public void Show()
        {
            Console.WriteLine("這是基類中的內容。");
        }
    }
    public class Derivedclass : Baseclass
    {
        public void shownew()
        {
            Console.WriteLine("這是派生類中的內容。");
        }
    }
    class Example
    {
        static void Main(string[] args)
        { 
            Derivedclass aclass=new Derivedclass();
            aclass.Show();
            aclass.shownew();
        }
    }
}

程式碼顯示結果:

    這是基類中的內容。

    這是派生類中的內容。

    分析:Derivedclass 繼承 Baseclass類,在Example這個類中例項化Derivedclass物件aclass,然後分別呼叫基類派生類中的方法,這種形式通過繼承實現了派生類對於基類的擴充。

 

   (二)、派生類成員隱藏基類成員

<span style="font-size:14px;">namespace JiCheng
{
    public class Baseclass
    {
        public void Show()
        {
            Console.WriteLine("這是基類中的內容。");
        }
    }
    public class Derivedclass : Baseclass 
    {
        public void Show()
        {
            Console.WriteLine("派生類的方法隱藏了基類的方法");
        }
    }
    class Example
    {
        static void Main(string[] args)
        {
            Derivedclass newclass = new Derivedclass();
            newclass.Show();
        }
    }
}</span><span style="font-size:32px;">
</span>

    結合第一個例子,該例子中基類和派生類中的方法名相同,此時的結果為:

     派生類的方法隱藏了基類的方法。

 

    然而此時會有提醒:

                

    我們在派生類中把方法改為:publicnew void Show()即可去掉該警告,從而實現對基類方法的隱藏。

    通過這兩個例子以及上一篇部落格中對UML圖中繼承的關係可知,對於最基本的繼承實現已經可以掌握。

 

二、訪問修飾符對繼承性的影響


基類訪問修飾符

可以訪問的型別

可以訪問的型別

可以訪問的型別

Public

基類

派生類

外部程式碼

Protected

基類

派生類

 

private

基類

 

 

   這張表是我對基類中三類訪問修飾符對於外部程式碼、派生類何時訪問的總結。

   舉例:

   就像上面第一個例子中,Baseclass為基類,Derivedclass為派生類,Example為外部程式碼。此時,對於Baseclass的訪問,則要根據Baseclass中訪問修飾符來決定了。

   如果Baseclass中Show()方法的訪問修飾符是public,則Derivedclass和Example均可對其進行訪問,同理,若是protected,在Derivedclass中可以訪問,但是在Example中儘管例項化Derivedclass也不可以實現對基類的訪問(通過實驗驗證)。

而對於private,僅僅能在Baseclass中對其進行呼叫(程式碼仍為上面的程式碼,對基類的訪問修飾符進行修改即可)。

 

三、 重寫與base關鍵字

(一)、重寫

    派生類可能要執行基類中同名成員的不同任務時,這就需要重寫的過程了。同時重寫時基類方法必須是要用abstract、virtual、override(多重繼承)這些修飾符進行修飾的。

    問:為何需要在重寫的時候用到abstractvirtualoverride

    答:請看上面所舉例子中的警告:

                       

         若不是繼承抽象的、虛的、繼承的方法,則基類的方法將會被隱藏。

    程式碼格式:

Public class Baseclass  //基類
{
	Public virtual void Show()	//基類方法
{
Console.WriteLine(“基類中的方法”);
}
}
Public class Derivedclass:Baseclass //派生類
{
	Public override void Show()  //派生類方法
{
	Console.WriteLine(“派生類中過載的方法”)
}	
}

    在外部程式碼中例項化派生類,派生類物件呼叫Show方法,則顯示:

    “派生類中過載的方法”

    由此區別於隱藏基類方法的例子,但是若要對基類中的Show方法同時呼叫,這時就需要用到base關鍵字。

 

(二)、base關鍵字

    Base關鍵字的作用可以總結為:

    1、 呼叫已經被重寫的基類的方法;

    2、 呼叫建構函式;

 

   程式碼展示:

   1、 呼叫已經被重寫的基類的方法

class Baseclass
     {
	 	Public virtual void Show()
{
}
}
Class Derivedclass:Baseclass
{
	Public override void Show()
   {
	Base.Show();  //此時在該方法中則呼叫了基類中的方法。
}
}
   2、呼叫建構函式

namespace JiCheng
{
    public class Baseclass
    {
        int num;
        public Baseclass() //建構函式一
        {
            Console.WriteLine("基類建構函式一:Baseclass()");
        }
        public Baseclass(int i) //帶引數的建構函式
        {
            num = i;
            Console.WriteLine("基類建構函式二:Baseclass(int i)");
        }
    }

    public class Derivedclass : Baseclass
    {
        public Derivedclass()
            : base() //呼叫建構函式一
        { 
        }
        public Derivedclass(int i)
            : base(i) //呼叫帶引數的建構函式
        { 
        }
    }
    class program
    {
        static void Main(string[] args)
        {
            Derivedclass see = new Derivedclass();  //例項化派生類,意在呼叫無參的建構函式;
            Derivedclass para = new Derivedclass(3);  //例項化派生類,同時呼叫含有引數的建構函式。
        }
    }
}

    在上面的例子中:

            public classDerivedclass : Baseclass

            {

                  publicDerivedclass()

                       :base()//呼叫建構函式一

                  {

                  }

                 publicDerivedclass(int i)

                      :base(i)//呼叫帶引數的建構函式

               {

               }

          }

結果:

   基類建構函式一:Baseclass()

   基類建構函式二:Baseclass(inti)

   Base如上所述用來對基類建構函式進行呼叫,在《大話設計模式》的學習中,大量的例子中都有這樣的呼叫,學習要在知其然的同時更要知其所以然,以後再遇到base關鍵字的時候,就再也不怕了。

 

    總結:通過對C#繼承進行詳細的總結,之前問題本上遺留的一些繼承、base關鍵字、訪問修飾符等問題基本上都解決了,對於在設計模式中程式碼的認識也有了新的高度。不足之處即總結的過於冗餘,寫完之後才發現寫了這麼多東西,以後儘量精簡一寫。

    遺留問題:重寫時abstract方法和virtual方法如何進行區別?什麼時候用?希望能和大家一起交流。






相關文章