C#基础--类/接口/成员修饰符,多态、重载、重写,静态和非静态
C#基礎--類/接口/成員修飾符,多態、重載、重寫,靜態和非靜態
?
類/接口/成員修飾符
C#修飾符---接口:
接口默認訪問符是internal
接口的成員默認訪問修飾符是public
C#修飾符--類:
public、internal、 partial、abstract、sealed、static
C#修飾符--類成員修飾符:
public、protected、private、internal、sealed、abstract、virtual、override、readonly、const
簡單介紹:
?
Public:最開放,所有的本程序集以及其他的程序集里面的對象都能夠訪問
Protected:比較開放,自身成員以及子類成員可訪問
Private:只有自身成員才能夠訪問
Internal:本程序集內的成員可以訪問
Partial:部分類,可以將一個類分成幾部分寫在不同文件中,最終編譯時將合并成一個文件,且各個部分不能分散在不同程序集中
Abstract:修飾類的時候表示該類為抽象類,不能夠創建該類的實例。修飾方法的時候表示該方法需要由子類來實現,如果子類沒有實現該方法那么子類同樣是抽象類;且含有抽象方法的類一定是抽象類
Sealed:修飾類時表示該類不能夠被繼承,修飾方法時表示該方法不能被覆寫。
Static:修飾類時表示該類時靜態類,不能夠實例化該類的對象,既然不能實例化該類,那么這個類也就不能夠含有對象成員,即該類所有成員為靜態;修飾類成員時,該成員為類成員,只能通過【類.成員名】的方式訪問
當static修飾構造函數時,構造函數不能含有任何參數,不能含有修飾符,構造函數不能對對象成員進行初始化操作。但是能夠對靜態成員進行初始化或者調用。不能保證他在什么時候執行,卻能保證在第一次使用類型前執行。在靜態構造函數中初始化的靜態成員為最終初始化結果。
Virtual:修飾方法成員,表示虛方法。父類可以含有該類的實現,子類可以覆寫該函數。
Override:表示該方法為覆寫了父類的方法。
Readonly:修飾字段,表示該字段為只讀字段。
注意:readonly修飾引用類型時由于操作不當可能修改該只讀對象狀態。例如:
Readonly List< Person> persons=….;
我們可能在某些地方對persons 進行了修改:persons.add(new Person());
Const:修飾字段,表示該字段為只讀字段。并且在編譯時必須能夠明確知道該字段的值,其值是硬編碼到程序中去的,修改了該類型成員后需要重新編譯才能使修改生效。
而readonly是運行時只讀,內容在運行時確定,所以修改了readonly類型成員后無需重新編譯即可生效。
Readonly不能修飾局部變量,const可以。
注意:當一個類或方法沒有被任何修飾符修飾時,默認為internal:
?
多態、重載、重寫
重寫:是指重寫基類的方法,在基類中的方法必須有修飾符virtual,而在子類的方法中必須指明override。
格式如下:
1.在基類中:?
1 public virtual void myMethod() 2 { 3 }2.在子類中:?
1 public override void myMethod() 2 { 3 }重寫以后,用基類對象和子類對象訪問myMethod()方法,結果都是訪問在子類中重新定義的方法,基類的方法相當于被覆蓋掉了。
重載:用于在給定了參數列表和一組候選函數成員的情況下,選擇一個最佳函數成員來實施調用。
1 public void test(intx,inty){} 2 3 public void test(intx,refinty){} 4 5 public void test(intx,inty,stringa){}重載的特征:
- 方法名必須相同
- 參數列表必須不相同,與參數列表的順序無關
- 返回值類型可以不相同
但如果有泛型,就要注意了!
多態:c#的多態性主要體現在類的繼承上
子類繼承父類的時候,可能出現同名但方法定義不同的情況,?所以在子類中會將原方法覆蓋,實現自身的要求.
總結一句話:通過繼承實現的不同對象調用相同的方法,表現出不同的行為,稱之為多態。
需要注意的地方有兩點:
例子1:
代碼public class Animal{public virtual void Eat(){Console.WriteLine("Animal eat");}}public class Cat : Animal{public override void Eat(){Console.WriteLine("Cat eat");}}public class Dog : Animal{public override void Eat(){Console.WriteLine("Dog eat");}}class Tester{static void Main(string[] args){Animal[] animals = new Animal[3];animals[0] = new Animal();animals[1] = new Cat();animals[2] = new Dog();for (int i = 0; i < 3; i++){animals[i].Eat();}}}輸出結果:
Animal eat...
Cat eat...
Dog eat...
在上面的例子中,通過繼承,使得Animal對象數組中的不同的對象,在調用Eat()方法時,表現出了不同的行為。
多態的實現看起來很簡單,要完全理解及靈活的運用c#的多態機制,也不是一件容易的事
例子2:override實現多態
多層繼承中又是怎樣實現多態的。比如類A是基類,有一個虛擬方法method()(virtual修飾),類B繼承自類A,并對method()進行重寫(override修飾),現在類C又繼承自類B,是不是可以繼續對method()進行重寫,并實現多態呢?看下面的例子。
1 代碼 2 3 public class Animal 4 { 5 public virtual void Eat() 6 { 7 Console.WriteLine("Animal eat"); 8 } 9 } 10 11 public class Dog : Animal 12 { 13 public override void Eat() 14 { 15 Console.WriteLine("Dog eat"); 16 } 17 } 18 19 public class WolfDog : Dog 20 { 21 public override void Eat() 22 { 23 Console.WriteLine("WolfDog eat"); 24 } 25 } 26 27 class Tester 28 { 29 static void Main(string[] args) 30 { 31 Animal[] animals = new Animal[3]; 32 33 animals[0] = new Animal(); 34 animals[1] = new Dog(); 35 animals[2] = new WolfDog(); 36 37 for (int i = 0; i < 3; i++) 38 { 39 animals[i].Eat(); 40 } 41 } 42 }運行結果為:
Animal eat...
Dog eat...
WolfDog eat...?
在上面的例子中類Dog繼承自類Animal,對方法Eat()進行了重寫,類WolfDog又繼承自Dog,再一次對Eat()方法進行了重寫,并很好地實現了多態。不管繼承了多少層,都可以在子類中對父類中已經重寫的方法繼續進行重寫,即如果父類方法用override修飾,如果子類繼承了該方法,也可以用override修飾,多層繼承中的多態就是這樣實現的。要想終止這種重寫,只需重寫方法時用sealed關鍵字進行修飾即可。
例子3:abstract-override實現多態
用abstract修飾的抽象方法。抽象方法只是對方法進行了定義,而沒有實現,如果一個類包含了抽象方法,那么該類也必須用abstract聲明為抽象類,一個抽象類是不能被實例化的。對于類中的抽象方法,可以再其派生類中用override進行重寫,如果不重寫,其派生類也要被聲明為抽象類。看下面的例子。
1 代碼 2 3 public abstract class Animal 4 { 5 public abstract void Eat(); 6 } 7 8 public class Cat : Animal 9 { 10 public override void Eat() 11 { 12 Console.WriteLine("Cat eat"); 13 } 14 } 15 16 public class Dog : Animal 17 { 18 public override void Eat() 19 { 20 Console.WriteLine("Dog eat"); 21 } 22 } 23 24 public class WolfDog : Dog 25 { 26 public override void Eat() 27 { 28 Console.WriteLine("Wolfdog eat"); 29 } 30 } 31 32 class Tester 33 { 34 static void Main(string[] args) 35 { 36 Animal[] animals = new Animal[3]; 37 38 animals[0] = new Cat(); 39 animals[1] = new Dog(); 40 animals[2] = new WolfDog(); 41 42 for (int i = 0; i < animals.Length; i++) 43 { 44 animals[i].Eat(); 45 } 46 } 47 }運行結果為:
Cat eat...
Dog eat...
Wolfdog eat...
從上面可以看出,通過使用abstract-override可以和virtual-override一樣地實現多態,包括多層繼承也是一樣的。不同之處在于,包含虛擬方法的類可以被實例化,而包含抽象方法的類不能被實例化。
?
靜態和非靜態
靜態類和非靜態類
靜態類與非靜態類的重要區別在于靜態類不能實例化,也就是說,不能使用 new 關鍵字創建靜態類類型的變量。在聲明一個類時使用static關鍵字,具有兩個方面的意義:首先,它防止程序員寫代碼來實例化該靜態類;其次,它防止在類的內部聲明任何實例字段或方法。
靜態類是自C# 2.0才引入的,C# 1.0不支持靜態類聲明。程序員必須聲明一個私有構造器。私有構造器禁止開發者在類的范圍之外實例化類的實例。使用私有構造器的效果與使用靜態類的效果非常相似。
兩者的區別:
私有構造器方式仍然可以從類的內部對類進行實例化,而靜態類禁止從任何地方實例化類,其中包括從類自身內部。靜態類和使用私有構造器的另一個區別在于,在 使用私有構造器的類中,是允許有實例成員的,而C# 2.0和更高版本的編譯器不允許靜態類有任何實例成員。使用靜態類的優點在于,編譯器能夠執行檢查以確保不致偶然地添加實例成員,編譯器將保證不會創建此 類的實例。靜態類的另一個特征在于,C#編譯器會自動把它標記為sealed。這個關鍵字將類指定為不可擴展;換言之,不能從它派生出其他類。
靜態類的主要特性:
1:僅包含靜態成員。
2:無法實例化。
3:是密封的。
4:不能包含實例構造函數。
靜態成員
1:非靜態類可以包含靜態的方法、字段、屬性或事件;
2:無論對一個類創建多少個實例,它的靜態成員都只有一個副本;
3:靜態方法和屬性不能訪問其包含類型中的非靜態字段和事件,并且不能訪問任何對象的實例變量;
4:靜態方法只能被重載,而不能被重寫,因為靜態方法不屬于類的實例成員;
5:雖然字段不能聲明為 static const,但 const 字段的行為在本質上是靜態的。這樣的字段屬于類,不屬于類的實例。因此,可以同對待靜態字段一樣使用 ClassName.MemberName 表示法來訪問 const 字段;
6:C# 不支持靜態局部變量(在方法內部定義靜態變量)。
靜態構造函數
1:靜態類可以有靜態構造函數,靜態構造函數不可繼承;
2:靜態構造函數可以用于靜態類,也可用于非靜態類;
3:靜態構造函數無訪問修飾符、無參數,只有一個 static 標志;
4:靜態構造函數不可被直接調用,當創建類實例或引用任何靜態成員之前,靜態構造函數被自動執行,并且只執行一次。
注意:
1:靜態類在內存中是一直有位置的;
2:非靜態類在實例化后是在內存中是獨立的,它的變量不會重復,在使用后會及時銷毀,所以不會出現未知的錯誤。在C#中靜態成員是比較敏感的東西,在不是十分確認的情況下不要使用;
3:建議更多地使用一般類(非靜態類)。
使用選擇:
當定義的類不需要進行實例化時,我們使用靜態類;如果需要實例化對象,需要繼承等特性時,應該使用非靜態類,并且將統一使用的變量和方法設為靜態的,那么所有實例對象都能訪問。
?
轉載于:https://www.cnblogs.com/JiYF/p/6122475.html
總結
以上是生活随笔為你收集整理的C#基础--类/接口/成员修饰符,多态、重载、重写,静态和非静态的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【BZOJ1778】[Usaco2010
- 下一篇: django配置数据驱动,python安