【C#】OOP之繼承那點事

來源:互聯網
上載者:User

標籤:style   blog   http   color   java   使用   os   io   


前言:

繼承這點事,說多不多,說少不少,這裡只描述了一些我認為的基礎篇,望各位大神指教。
本節參照了C#進階編程和Think in java對繼承的描述,我個人認為OOP只是思想,故看明白一個就說通的,只是文法上的區別。

 

  • 許可權限制關鍵字
  • 類繼承
    • 類繼承基本寫法
    • 類繼承的好處 
    • 繼承中的Virtual(虛方法)
    • 抽象類別
    • 類繼承的壞處
    • 執行循序
    • 不可繼承的類
  • 介面繼承

 

1.類繼承    類繼承基本寫法:

    

 public class SuperClass : Object{} public class SubClass : SuperClass{}

   我們用":"來表示類的繼承, 而且每個類只能有一個父類(這個靠譜啊,你不可能有兩個親身父親,C++不論)。

   SuperClass繼承了Object類, Object類是頂級類,你自訂的頂級類(這裡說SuperClass)會自動繼承這個類(我看有很多人說:你的每個類都會繼承Object,我們說過,你只能有一個親生父親,這樣的說法不是很嚴謹,這樣的Tier1, Tier2, Tier3的層次下來,你的高層可以直接用Object所開放的一些方法)。

  

    類繼承的好處:  

  我們先來看些該死的溫柔(類)!!!

 public class Dog    {        public string Name { get; set; }        public string Age { get; set; }        public void Run()        {            Console.WriteLine("Dog is running.");        }    }    public class Cat    {        public string Name { get; set; }        public string Age { get; set; }        public void Run()        {            Console.WriteLine("Cat is running.");        }    }
View Code

  

  粗看一下,沒什麼問題,貓類和狗類 都有名字,年齡和一個跑的方法。 (當年,我寫完還點頭,雙手叉腰,嗯,很好,不錯--傻的一塌糊塗,冏)

  但是如果那天有個變態叫你把所有動物都寫一邊,你開始造輪子了,1234567.....,終於要完工了, 大喜過望,那個變態回來告訴你,不好意思,弄錯了,年齡沒有意義,可以去掉(納尼....). 這個時候你就需要再去1234567....,oh Fuck...難道我不能只改一次嗎?

  完 全 可 以->繼承

  

    public abstract class Animal    {        public string Name { get; set; }        public string Age { get; set; }        public void Run()        {            Console.WriteLine(string.Format("{0} is running.", Name));        }    }    public class Dog : Animal    {    }    public class Cat : Animal    {    }
View Code

  代碼所示之處我們提取一個父類:Aniaml(抽象類別..過後再說這個).我們重新來完成那個變態的需求,我們只要開闢一個類然後繼承一下Animal就好了,

(情境恢複)嘿,年齡沒有意義,可以去掉(簡單....),我們只要把Animal中的年齡去掉,就OK了,一步到位。

 

  到這裡看出來繼承的好處沒:消除你重複的代碼,讓修改更加的方便。

  

    繼承中的Virtual(虛方法)

  這裡又有人提出另一個問題了,如果我發現我父類的方法不能滿足我的條件了,但是我又不想重載,我能重寫嗎?答案:完全可以。

  

  C#提供一個Virtual的一個標識,可以用於方法重寫(java都說虛方法)

   

    public abstract class Animal    {        public string Name { get; set; }        public string Age { get; set; }        public virtual void Run()        {            Console.WriteLine(string.Format("{0} is running.", Name));        }    }    public class Dog : Animal    {        public override void Run()        {            Console.WriteLine("Dog is running.");        }    }    public class Cat : Animal    {    }
View Code

  看Animal中的Run方法加上了virtual標識這個方法說虛方法,也就說可以被重寫,在Dog類中,我們使用了override標識我們重寫了Run的方法,這樣我們在執行個體化對象Cat的時候,我調用Run方法就是我們重寫過的。

 

 有人提出疑問了:如果不寫virtual 和 override,直接在Cat中重寫Run方法,執行個體化Cat cat=new Cat()後調用Run方法也是一樣的結果。 回答:C#不像JAVA都說虛方法,如果不想寫virtual 和 override的話,CLR認為這個是隱藏,所以要在子類的Run方法上添加一個new關鍵字,如果不添加會出現
  warning。
public class Cat:Animal
{
public new void Run()
{
Console.WriteLine("....");
}
 }
New 關鍵字代表我要隱藏父類同名,同參數的方法(這裡有幾個可以討論的地方,在多態那章會提出來說)
   抽象方法
     為什麼會出現抽象方法,OOP告訴我們,執行個體化就像我們現實中創造一件東西,就如上例來看,我們如何去創造一個叫Animal的一個實體,這樣是不是很奇怪,所以我們出現了抽象類別。    抽象類別無法被執行個體化,只能被繼承使用。public abstract class Animal,在class前面定義abstract關鍵字就好了。

   抽象類別可以定義抽象的方法,用abstract關鍵字來標識,所有繼承該抽象類別的子類必須實現這個抽象方法,來一個執行個體:
  

 public abstract class Animal    {        public string Name { get; set; }        public string Age { get; set; }        public virtual void Run()        {            Console.WriteLine(string.Format("{0} is running.", Name));        }        public abstract void Scream();    }    public class Dog : Animal    {        public override void Run()        {            Console.WriteLine("Dog is running.");        }        public override void Scream()        {            throw new NotImplementedException();        }    }    public class Cat : Animal    {        public override void Scream()        {            throw new NotImplementedException();        }    }
View Code

  在Animal的抽象類別中(我們說了為什麼把Animal定義成抽象類別),定義了一個Scream()的抽象方法,我們看見了。抽象方法是沒有實現體的,直接後面跟上";"作為結束。在子類Dog和Cat類裡,我們實現了Scream這個方法(不可以不實現,只要你用IDE工具,編譯時間會報錯),我們在來看子類的Scream方法有override的關鍵字,所以abstract被認為是虛方法,用法類似。

  註:這裡還沒有說介面,抽象類別和介面一起用非常的常見,等說到介面,再詳細的來說下抽象類別的其他作用。

  

  類繼承的壞處  

    所謂有得必有失,繼承給我們帶來了很多好的地方,消除代碼重複,讓層次更加清晰,修改方便等好處,但是隨之帶來的壞處也是很明顯的,當我們繼承的層次變多了,整個的架構會變得十分臃腫而導致不清晰,拿個簡單的例子來說,假設我們說從猩猩進化而來,那尾巴是否已經沒有了,而猩猩還是有的,這就會導致使用的迷糊,我們做類的時候要把該類的東西放在此類中,做父類的時候把對應的公用的東西提出來,而一直用繼承的話很恐怖,所以這裡又引出一個新的概念->組合。

    組合概念就說在類中放一個其他類的對象,如果要用就賦值,不要用了就直接拿掉(父親我們總不能放棄吧)。

  執行循序

  

 public abstract class SuperClass    {        public static string StaticField = "StaticFieldInSuperClass";        private string _privateField = "_privateFieldInSuperClass";        public string publicField = "publicFieldInSuperClass";        public SuperClass()        {                  }    }    public class SubClass : SuperClass    {        public static string StaticFieldInDog = "StaticFieldInSubClass";        private string _privateField = "_privateFieldInSubClass";        public SubClass()        {        }    }
View Code

  我們看一下這兩個類SuperClass裡面有靜態欄位,私人欄位,共有欄位和一個構造,SubClass有一個靜態欄位,私人欄位。

  我們執行個體化SubClass subClass=new SubClass()的時候,執行循序如下:

  1.先初始化子類(subclass)的欄位。

  2.執行子類構造,這時會發現它擁有父類,所以暫停初始化子類構造,而初始化父類(SuperClass)

  3.初始化父類(SuperClass)的欄位

  4.執行父類構造

  5.返回子類繼續初始化子類構造

  這裡有興趣的朋友可以直接debug看步驟就明白了。

  不可繼承的類

    擁有關鍵字sealed類都不能被繼承。

    

    public sealed class ConfigHelper    {          }

  故可以認為裡面所有的欄位和方法都說內建sealed,因為無法繼承就無法重寫。

2.介面繼承

  pending...有點別的事..先發布了..。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.