C#學習筆記Day4
第四章 繼承
1.實現繼承和介面繼承
- 實現繼承:表示一個類派生於一個基型別,他擁有該基型別的所有成員欄位和函式,在實現繼承中,派生類採用基型別的每個函式的實現程式碼,除非在派生型別的定義中指定重寫某個函式的實現程式碼。在需要給現有型別新增功能,或許多相關的型別共享一組重要的公共功能時,這種型別的繼承非常重要。
- 介面繼承:表示一個型別只繼承了函式的簽名,沒有繼承任何實現程式碼。在需要指定該型別具有某些可用的特性時,最好使用這種型別的繼承。
2.多重繼承
C#不支援多重繼承。而c#又允許型別派生自多個介面-----多重介面繼承。這說明c#可以派生自另一個類和任意多個介面。
3.結構和類
結構是值型別,類是引用型別。使用結構的一個限制是結構不支援繼承,但每個結構都派生自System.ValueType。但結構可以實現介面。
4.虛方法
把一個基類函式宣告為Virtual,就可以在任何派生類中重寫該函式。也可以把屬性宣告為virtual。
C#中虛擬函式的概念與OOP(面向物件程式設計)的概念相同:可以在派生類中重寫虛擬函式。在呼叫方法時,會呼叫該類物件的合適方法。在c#中,函式預設不是虛的,但(除了建構函式以外)可以顯示的宣告為虛擬函式,在派生類的函式重寫另一個函式時,要使用override關鍵字顯示宣告。
成員欄位和靜態函式都不能宣告為virtual。
5.隱藏方法
如果簽名相同的方法在基類和派生類中都進行了宣告,但該方法沒有分別宣告virtual和override,派生方法就會隱藏基類方法。
虛方法與隱藏方法的區別:
虛方法:將一個基類函式宣告為virtual
class MyBaseClass
{
public virtual string VirtualMethod()
{
return "Method is called in base class."
}
}
在派生類中進行重寫該函式時,需要使用override關鍵字顯示宣告
class MyDerivedClass : MyBaseClass
{
public override string VirtualMethod()
{
return "Method is called in derived class."
}
}
當在子類中重寫虛擬函式之後,不管在哪裡進行呼叫,呼叫的都是重寫後的方法(相當於原先的方法被重寫後的方法給覆蓋了)。
隱藏和重寫的區別:
隱藏:只是將父類中的方法給隱藏了,實際這個方法還存在。
重寫:將原先父類中的方法完全重寫了,原先的方法是不存的了。
//隱藏方法:如果使用子類宣告的物件,則呼叫隱藏方法會呼叫子類的;如果使用父類宣告的物件,則會呼叫父類中的隱藏方法。
//父類:Enemy
//子類:Boss
//Move()是一個隱藏方法
class Enemy
{
public string Move()
{
return "This is Move from Enemy!";
}
}
class Boss : Enemy
{
public new string Move()
{
return "This is Move from Boss!";
}
}
Boss boss = new Boss();
boss.Move(); //This is Move from Boss!
Enemy boss = new Boss();
boss.Move(); //This is Move from Enemy! //構造一樣,但是宣告不一樣,呼叫的隱藏方法也是不一樣的。
一般不去使用隱藏方法,因為很容易引起方法呼叫的混亂。
---------------------
原文:https://blog.csdn.net/lym940928/article/details/79833406
6.呼叫函式的基類版本
語法:base.BaseMethodName()
7.抽象類和抽象函式
C#允許把類和函式宣告稱Abstract。抽象類不能例項化,而抽象函式不能直接實現,必須在非抽象的派生類中重寫。顯然,抽象函式本身也是虛擬的。如果類包含抽象函式,那麼該類也是抽象的,也必須宣告為抽象。
8.密封類與密封方法
C#允許把類和方法宣告為sealed。對於類,這表示不能繼承該類,對於方法,表示不能重寫該方法。
9.派生類的建構函式
建構函式的呼叫順序是先呼叫System.Object,再按照層次結構由上向下進行,直到到達編譯器要例項化的類為止。還要注意在這個過程中,每個建構函式都初始化他自己的類中的欄位。
注意建構函式的執行順序。最先呼叫的總是基類的建構函式。也就是說,派生類的建構函式可以在執行過程中呼叫他可以訪問的任何基類的方法、屬性和任何其他成員變數,因為基類已經構造出來了。
- 在層次結構中新增無引數的建構函式
public abstract class SmallCar
{
private string description;
public SmallCar():base()
{
description=”This is SmallCar”;
}
}
在建構函式中添加了對基類建構函式的呼叫,這次使用的關鍵字是base而不是this,表示這是基類的建構函式,而不是當前類的建構函式。在base關鍵字後面的圓括號裡沒有引數,因為沒有給基類建構函式傳遞任何引數。
如果編譯器沒有在左花括號前面找到另一對建構函式的任何引用,他就會假定我們要呼叫的是基類的建構函式。
注:如果建構函式為私有的,會造成編譯錯誤,該錯誤不會發生在基類中,而出現在他的派生類中。
- 在層次結構中新增有引數的建構函式
public abstract class SmallCar
{
private string description;
public SmallCar(string description)
{
This.description=description;
}
}
public class miniCar:SmallCar
{
public miniCar(string description)
: base(description)
{
}
}
miniCar本身不能初始化description,但是可以把他傳遞給基類,以便基類建構函式進行處理,它本身不需要任何操作。
10.修飾符
修飾符 |
應用於 |
說明 |
Public |
所有型別或成員 |
任何程式碼均可以訪問該項 |
Protected |
型別和內嵌型別的所有成員 |
只有派生類能訪問該項 |
Internal |
所有型別或成員 |
只能在包含他的程式集中訪問該項 |
Private |
型別和內嵌型別的所有成員 |
只能在它所屬的型別中訪問該成員 |
Protected internal |
型別和內嵌型別的所有成員 |
只能在包含它的程式集和派生型別的任何程式碼中訪問該項 |
型別定義可以是共有的也可以是私有的,但不能把型別定義為protected、private和protected internal,因為這些修飾符對於包含在名稱空間中的型別沒有意義。但是這些型別可以應用於巢狀的型別(即包含在其他型別中的型別)。如果有巢狀型別,則內部型別總是可以訪問外部型別的所有成員。
public class OutClass
{
protected class InnerClass
{
//
}
//
}
其他修飾符
修飾符 |
應用於 |
說明 |
New |
函式成員 |
成員用相同的簽名隱藏繼承的成員 |
Static |
所有成員 |
成員不作用於類的具體例項 |
Virtual |
僅函式成員 |
成員可由派生類重寫 |
Abstract |
僅函式成員 |
虛擬成員定義了成員的簽名,但沒有提供實現程式碼 |
Override |
僅函式成員 |
成員重寫了繼承的虛擬或抽象成員 |
Sealed |
類、方法和屬性 |
對於類,不能繼承自密封類。對於屬性和方法,成員重寫已繼承的虛擬成員,但任何派生類中的任何成員都不能重寫該成員。該修飾符必須與override一起使用 |
Extern |
僅靜態方法 |
成員在外部用另一種語言實現 |