關於父類引用指向子類對象

來源:互聯網
上載者:User

標籤:

例如: 有以下2個類

public  class  Father        {            public int age = 70;                                   public static string name = "父親";                }        public class Son : Father        {            public int age = 30;                                public static string name = "兒子";                        }

Father f=new Son();

這種用法叫做“父類引用指向子類對象,或者叫“父類指標指向子類對象”,指的是定義一個父類的引用,而它實際指向的是子類建立的對象。

好處是什麼?

下面做幾個測試,

第一種  ,父類變數,調用 屬性  例如下面的  f.age   是一個父類的變數調用了屬性,問題是這裡的屬性是父類的?還是子類的? 答案是父類的屬性

class Program    {        static void Main(string[] args)        {            Father f=new Son();            Console.WriteLine(f.age);   //這裡輸出的是父類的年齡?還是子類的年齡? 答案是父親的年齡 70 ,因為這裡的f是個父類類型,所以是調用父類的屬性            Son s = f as Son;            Console.WriteLine(s.age);  //這裡輸出的父類的年齡?還是子類的年齡? 答案是子類的年齡 30            Console.ReadKey();        }        public  class  Father        {            public int age = 70;                      //第4執行            public static string name = "父親";       //第3執行        }        public class Son : Father        {            public int age = 30;                    //第2執行            public static string name = "兒子";    //第1執行                    }    }

小結論(1): 當用父類的變數調用屬性的時候,取決於聲明的類型(“=”左邊是什麼類型),而不是後面執行個體化的類型

第二種 ,父類變數,調用 方法 (父類的方法和子類的方法  一模一樣,子類並無重寫)

public  class  Father        {            public int age = 70;                      //第4執行            public static string name = "父親";       //第3執行            public void SayHi()            {                Console.WriteLine(string.Format("父親說,年齡{0},名字是{1}",age,name));            }        }        public class Son : Father        {            public int age = 30;                    //第2執行            public static string name = "兒子";    //第1執行            public void SayHi()            {                Console.WriteLine(string.Format("兒子說,年齡{0},名字是{1}", age, name));            }        } static void Main(string[] args)        {                        Father f = new Son();            f.SayHi();   //這裡調用的是父類的方法,因為f是父類,並且子類,壓根就沒有重寫   父親說,年齡是70,名字是父親            Son s = f as Son;            s.SayHi();   //這裡調用的是父類的方法?還是子類的方法?  答案是子類的方法,因為s是子類   兒子說,年齡是30,名字是兒子            Console.ReadKey();        }

小結論(2): 當子類和父類的方法完全相同時,調用的時候取決於聲明的類型(“=”左邊),而不是後面執行個體化的類型。

第三種 ,父類變數,調用 方法 (父類的方法和子類的方法 一模一樣 ,但是父類的方法加 Virtual , 子類不重寫)

小結論(3):如果父類有virtual虛方法,但是子類並沒有重寫的話,那麼  同上面的小結論(2)一樣,調用的時候,取決於聲明的類型(“=”的左邊),而不是執行個體化的類型

第四種 ,父類變數,調用 方法 (父類的方法和子類的方法 一模一樣 ,但是父類的方法加 Virtual , 子類重寫)

小結論(4):重寫以後,調用哪個類的方法取決於執行個體化的類型(“=”右邊)或者是轉換後最終的類型

第五種 ,父類變數,調用 方法 (父類的方法和子類的方法 一模一樣 ,但是父類的方法加 Virtual , 子類重寫)

父類變數指向子類的執行個體,但是我們直接調用父類變數下的屬性,會輸出子類的屬性?還是父類的屬性?答案是父類的屬性.

那如果再繼續調用方法的話,是調用父類的方法?還是子類的方法?答案是,如果是虛方法,子類有重寫,就調用子類的,子類沒有重寫,就調用父類的.

小結論(5) : 如果子類方法裡面想調用父類的屬性或者是方法,使用 base 關鍵字

 

結論:

1:當用父類的變數調用屬性的時候,取決於聲明的類型(“=”左邊是什麼類型),而不是後面執行個體化的類型

例如 輸出 f.age 就是輸出父類的屬性 ,而不是子類的屬性

2:當子類和父類的方法完全相同時,調用的時候取決於聲明的類型(“=”左邊),而不是後面執行個體化的類型。

也就是子類沒有重寫的時候. f.sayhi 就是調用的父類的sayhi ,而不是子類的sayhi

3 如果子類有重寫(override)父類的方法,那麼 父類變數調用方法的時候,就變成使用 子類的方法.

也就是子類有override的時候,f.sayhi 就是調用子類的sayhi

4:如果想在子類裡面訪問父類的屬性或者是方法,使用 base 關鍵字

 

C#中new和override的區別;abstract

當父類裡面有 virtual 方法的時候,子類可以使用 override 進行重寫.  那麼  f.sayhi  就變成調用子類的sayhi

不論父類的方法有沒有virtual,子類都可以在同名的方法上加一個new表示這是子類自己的方法,那麼父類的方法就會被隱藏起來, f.sayhi 就會變成 調用父類的sayhi,因為子類並沒有override. 如果這個時候,把new去掉,效果也是一樣的,f.sayhi 也是調用父類的sayhi, 判斷是否調用子類的方法,就看子類是否有override重寫.

//在C#中,override和new都會覆蓋父類中的方法。那它們兩者之前有什麼區別呢? //override是指“覆蓋”,是指子類覆蓋了父類的方法。子類的對象無法再訪問父類中的該方法(當然了,在子類的方法中還是可以通過base訪問到父類的方法的)。

//new是指“隱藏”,是指子類隱藏了父類的方法,當然,通過一定的轉換,可以在子類的對象中訪問父類的方法。

 

c#類的初始化順序

子類的靜態成員變數,子類的普通成員,父類的靜態成員,父類的普通成員

namespace 類的初始化順序{    class Program    {        static void Main(string[] args)        {            Father f=new Son();               Console.ReadKey();        }        public  class  Father        {                 public int age = 70;                            //第4執行            public static string name = "父親";       //第3執行        }        public class Son : Father        {                 public int age = 30;                         //第2執行            public static string name = "兒子";    //第1執行                    }    }}

首次訪問:(在此沒有顯示的寫出類中的構造方法) 
順序:子類的靜態欄位==》子類靜態構造==》子類非靜態欄位==》父類的靜態欄位==》父類的靜態構造==》父類的非靜態欄位 
==》父類的建構函式==》子類的建構函式 
非首次訪問:順序是一樣的,只不過少了中間靜態欄位和構造的過程 
對於靜態變數與靜態建構函式而言, 無論對一個類建立多少個執行個體,它的靜態成員都只有一個副本。 也就是說,靜態變數與靜態建構函式只初始化一次(在類第一次執行個體化時)

關於父類引用指向子類對象

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.