面向对象编程之C#
面向對象編程之C#
學些面向對象編程語言已經有一段時間了。現在借學習C#的機會把這方面的知識匯總歸納一下。
首先在這種思想指導下,把任何事物都高度抽象成為一個一個的類,每個類都具有它自己的字段和屬性以
及方法。每個類在被實例化之后就變成一個具體的對象,每個同類的對象在結構上是一致的,不同的是他
們各自的字段和屬性的值是不同的。如果一個類有公共的靜態變量和靜態方法。那么就算這個類沒有被實
例化也可以使用這些公共的靜態方法和變量。
類是可以進行繼承的,通過繼承可以在一組相似類之間,建立一種父子關系。父類于子類之間的關系既有
相同又有不同。子類繼承自父類,所以擁有父類一切特征,但是子類也有自己的個性,可以在需要時重載
父類的特性例如:方法。這樣相同的方法名,但父類和子類可以有不同的處理方式得到不同的結果。
C#支持實現繼承,但不支持多重實現繼承。也就是說一個類之能繼承自另一個類,不能繼承自多個類。C#
還支持接口繼承,并且允許多重接口繼承。所以雖然一個類不能繼承自多個類,但可以繼承自多個接口,
并且實現這些接口。接口繼承通常被看作一種契約:通過類型派生于接口,從而確保為客戶提供某個功能
。
要聲明一個類繼承自另一個類,語法如下:
class MyClass : BaseClass
{
???? ......
}
要聲明一個類繼承自另一個類和其他多個接口,語法如下:
public class MyClass : BaseClass, IInterface1,IInterface2
{
???? ......
}
虛方法
可以將基類中的方法或者屬性聲明為 virtual。這樣就可以在繼承自他的子類中重載這些方法或屬性。與
C++不同的是,在C#中重載必須使用 override 關鍵字顯示聲明。這樣可以避免C++中易犯的一個錯誤,就
是重載聲明的方法或屬性在基類中沒有對應的聲明。在C#中這會產生一個編譯錯誤。
如果不將基類的方法或屬性聲明為 virtual,而在子類中使用了相同聲明的方法或屬性,那么編譯時就會
產生一個警告。告訴你基類中的有關方法被子類隱藏了。這不是錯誤程序依然可以執行,但容易引起誤會
。因為此時相同的方法名返回何種結果就要看對象的類型了。如果是基類對象就按照基類的方法返回,如
果是子類對象就按照子類方法返回。要去掉這樣的警告可以在子類的同名方法或屬性申明時加上 new 關
鍵字,來顯示的隱藏基類的同名方法。
另外可以使用 base.<方法/屬性> 在子類中調用基類的方法或屬性。
例如:Program.c
?1?using?System;?2?using?System.Collections.Generic;
?3?using?System.Text;
?4?
?5?namespace?Lesson1
?6?{
?7?????class?BaseClass
?8?????{
?9?????????private?string?clsName;
10?????????public?virtual?string?Name
11?????????{
12?????????????get?{?return?clsName;?}
13?????????????set?{?clsName?=?value;?}
14?????????}
15?
16?????????public?virtual?string?VirtualMethod1()
17?????????{?return?"This?is?BaseClass?VirtualMethod1.";?}
18?
19?????????public?virtual?string?VirtualMethod2()
20?????????{?return?"This?is?BaseClass?VirtualMethod2.";?}
21?
22?????????public?string?Method()
23?????????{?return?"This?is?BaseClass?Method.";?}
24?????}
25?
26?????class?MyClass?:?BaseClass
27?????{
28?????????public?override?string?VirtualMethod1()
29?????????{?
30?????????????return?"This?is?MyClass?OverrideMethod?from?BaseClass?VirtualMethod1.";?
31?????????}
32?
33?????????public?override?string?Name
34?????????{
35?????????????get?{?return?base.Name;?}
36?????????????set?{?base.Name?=?value;?}
37?????????}
38?
39?????????//?警告?1?'Lesson1.MyClass.Method()'?hides?inherited?member?
40?
41?'Lesson1.BaseClass.Method()'.?
42?????????//??????????Use?the?new?keyword?if?hiding?was?intended.?
43?????????//??????????D:\Docoment\Visual?Studio?2005\Projects\Lesson1\Lesson1\Program.cs?37?
44?
45?23?Lesson1
46?????????public?new?string?Method()
47?????????{
48?????????????string?rs?=?base.Method();
49?????????????return?"This?is?MyClass?Method.?"?+?rs;
50?????????}
51?????}
52?
53?????class?Program
54?????{
55?????????static?void?Main(string[]?args)
56?????????{
57?????????????BaseClass?b?=?new?BaseClass();
58?????????????MyClass?a?=?new?MyClass();
59?????????????
60?????????????b.Name?=?"BaseClass";
61?????????????a.Name?=?"MyClass";
62?
63?????????????Console.WriteLine(b.Name?+?"??"?+?b.Method());
64?????????????Console.WriteLine(a.Name?+?"??"?+?a.VirtualMethod1());
65?????????????Console.WriteLine(a.Name?+?"??"?+?a.VirtualMethod2());
66?????????????Console.WriteLine(a.Name?+?"??"?+?a.Method());
67?????????????Console.ReadKey();
68?????????}
69?????}
70?}
71?
?
抽象類和抽象函數
C#允許把類和函數聲明為 abstract 抽象類或抽象函數。抽象類是不能實例化的,只提供給子類繼承。抽
象函數則不需提供具體實現的代碼,只要聲明一個方法名就可以了。抽象類中可以聲明非抽象的函數,但
抽象函數只能在抽象類中聲明,如在非抽象類中聲明抽象函數會導致編譯錯誤。對于抽象類的私有變量可
以在聲明時提供初始值。例如:
??? abstract class MyAbstractClass
??? {
??????? private int result = 0;
??????? public abstract int AbstractMethod();
??????? public int MyMethod()
??????? {
??????????? return result;
??????? }
??? }
密封類和密封方法來終止繼承
當把一個類或函數聲明為 sealed 時,那么其他類就不能再繼承這個類或者重寫這個函數。在編寫自己的
框架時可以用這種方法來防止其他用戶繼承類或重寫函數。例如:.NET類庫就大量使用了密封類。
例如:
??? sealed class MyFinalClass
??? {
??????? // ......
??? }
注意構造函數的執行順序。基類的構造函數總是最先調用。也就是說,派生類的構造函數可以在執行過程
中調用基類的方法、屬性和其他成員,因為基類已經構造出來的其他字段也已經初始化了。
?
訪問修飾符
對類或類的成員可以使用 public、protected、internal、private 和 protected internal 這些修飾符
定義類或成員的可見性。
public??????????????? 所有類型或成員????????????? 任何代碼均可訪問
protected???????????? 類型和內嵌類型的所有成員??? 只有派生的類型可以訪問
internal????????????? 類型和內嵌類型的所有成員??? 只能在包含它的程序集中訪問它
private?????????????? 所有類型或成員????????????? 只能在它所屬的類型中訪問它
protected internal??? 類型和內嵌類型的所有成員??? 只能在包含它的程序集和派生類型的代碼中訪問
注:在命名空間下的元素不能使用private, protected, 或 protected internal 這些修飾符。只能使用
public 或 internal 來修飾。但C#中類可以嵌套聲明,當一個類在另一個類中定義時,可以作為另一個
類的成員被指定protected來聲明。如果有嵌套的類,那么內部的類總可以訪問外部類的所有成員,甚至
是私有成員。
如果C#中定義的一個類如果沒有任何修飾符,那么它默認的訪問修飾符是私有的。使用 public 這個修飾
符后無論是類還是方法,均可在任意代碼區域訪問到。使用 protected 定義的成員,只有繼承該類的類
能夠訪問。使用 internal 定義的成員,能夠在當前解決方案(即當前程序集)中有效,也就是該類的實例
對象和繼承自該類的代碼都可以訪問。如果一個成員被定義為 private 那么它就只能在這個類的代碼范
圍內訪問。使用 protected internal 定義的成員,能夠在當前解決方案(即當前程序集)中有效。
其他修飾符
new???????????????? 函數成員???????????????????? 隱藏或重寫基類函數
static????????????? 所有成員???????????????????? 聲明靜態成員,不需要實例化就可使用
virsual???????????? 類和函數???????????????????? 聲明可以被重載的函數
abstract??????????? 類和函數???????????????????? 只聲明函數,不做具體實現由繼承類實現
override??????????? 函數成員???????????????????? 重載函數時的顯示聲明
sealed????????????? 類和函數???????????????????? 用于顯示聲明該類或方法不能再被繼承
extern????????????? 用于靜態[DLLImport]方法????? 說明在外部實用另一語言實現
?
接口
一般情況下,接口中只能包含方法、屬性、索引器和事件的聲明。作為公共契約,接口不能被實例化,只
能包含成員的定義。接口不能有構造函數或字段,也不允許包換運算符重載。除此之外,接口還不允許聲
明成員的修飾符,因為接口的成員都是公共的,不需要再聲明成為其他類型。也不能將成員聲明成虛擬或
靜態的。接口可以互相繼承就像類一樣,如果一個類要實現一個接口,而這個接口又是派生于另一個接口
,那么這個類就需要實現這兩個接口所聲明的全部成員。
例如:
?
??1?using?System;??2?using?System.Collections.Generic;
??3?using?System.Text;
??4?using?Lesson.Interface;
??5?using?Lesson.VenusBank;
??6?using?Lesson.JupiterBank;
??7?
??8?namespace?Lesson.Interface
??9?{
?10?????public?interface?IBankAccount
?11?????{
?12?????????void?PayIn(decimal?amount);
?13?????????bool?Withdraw(decimal?amount);
?14?????????decimal?Balance?{?get;?}
?15?????}
?16?
?17?????//?接口的繼承
?18?????public?interface?ITransferBankAccount?:?IBankAccount
?19?????{
?20?????????//??????????????把接口引用當作傳遞參數傳遞
?21?????????bool?TransferTo(IBankAccount?destination,?decimal?amount);
?22?????}
?23?}
?24?
?25?namespace?Lesson.VenusBank
?26?{
?27?????public?class?SaverAccount?:?IBankAccount
?28?????{
?29?????????private?decimal?balance;
?30?
?31?????????public?void?PayIn(decimal?amount)
?32?????????{
?33?????????????balance?+=?amount;
?34?????????}
?35?
?36?????????public?bool?Withdraw(decimal?amount)
?37?????????{
?38?????????????if?(balance?>=?amount)
?39?????????????{
?40?????????????????balance?-=?amount;
?41?????????????????return?true;
?42?????????????}
?43?????????????Console.WriteLine("Withdrawal?attempt?failed.");
?44?????????????return?false;
?45?????????}
?46?
?47?????????public?decimal?Balance
?48?????????{
?49?????????????get?{?return?balance;?}
?50?????????}
?51?
?52?????????public?override?string?ToString()
?53?????????{
?54?????????????return?String.Format("Venus?Bank?Saver:?Balance?=?{0,6:C}",?balance);
?55?????????}
?56?????}
?57?}
?58?
?59?namespace?Lesson.JupiterBank
?60?{
?61?????public?class?GoldAccount?:?IBankAccount
?62?????{
?63?????????private?decimal?balance;
?64?
?65?????????public?void?PayIn(decimal?amount)
?66?????????{
?67?????????????balance?+=?amount;
?68?????????}
?69?
?70?????????public?bool?Withdraw(decimal?amount)
?71?????????{
?72?????????????if?(balance?>=?amount)
?73?????????????{
?74?????????????????balance?-=?amount;
?75?????????????????return?true;
?76?????????????}
?77?????????????Console.WriteLine("Withdrawal?attempt?failed.");
?78?????????????return?false;
?79?????????}
?80?
?81?????????public?decimal?Balance
?82?????????{
?83?????????????get?{?return?balance;?}
?84?????????}
?85?
?86?????????public?override?string?ToString()
?87?????????{
?88?????????????return?String.Format("Jupiter?Bank?Saver:?Balance?=?{0,6:C}",?balance);
?89?????????}
?90?????}
?91?}
?92?
?93?namespace?Lesson04
?94?{
?95?????public?class?CurrentAccount?:?ITransferBankAccount
?96?????{
?97?????????private?decimal?balance;
?98?
?99?????????public?void?PayIn(decimal?amount)
100?????????{
101?????????????balance?+=?amount;
102?????????}
103?
104?????????public?bool?Withdraw(decimal?amount)
105?????????{
106?????????????if?(balance?>=?amount)
107?????????????{
108?????????????????balance?-=?amount;
109?????????????????return?true;
110?????????????}
111?????????????Console.WriteLine("Withdrawal?attempt?failed.");
112?????????????return?false;
113?????????}
114?
115?????????public?decimal?Balance
116?????????{
117?????????????get?{?return?balance;?}
118?????????}
119?
120?????????public?override?string?ToString()
121?????????{
122?????????????return?String.Format("Current?Account:?Balance?=?{0,6:C}",?balance);
123?????????}
124?
125?????????//?實現轉帳功能
126?????????public?bool?TransferTo(IBankAccount?destination,?decimal?amount)
127?????????{
128?????????????bool?result;
129?????????????if?((result?=?Withdraw(amount))?==?true)
130?????????????????destination.PayIn(amount);
131?????????????return?result;
132?????????}
133?????}
134?
135?????class?Program
136?????{
137?????????static?void?Main(string[]?args)
138?????????{
139?????????????//?接口引用
140?????????????IBankAccount?venusAccount?=?new?SaverAccount();
141?????????????IBankAccount?jupiterAccount?=?new?GoldAccount();
142?
143?????????????//?存入
144?????????????venusAccount.PayIn(200);
145?????????????Console.WriteLine(venusAccount.ToString());
146?
147?????????????//?取出
148?????????????venusAccount.Withdraw(100);
149?????????????Console.WriteLine(venusAccount.ToString());
150?
151?????????????//?存入
152?????????????jupiterAccount.PayIn(500);
153?????????????Console.WriteLine(jupiterAccount.ToString());
154?
155?????????????//?取出
156?????????????jupiterAccount.Withdraw(600);
157?
158?????????????//?取出
159?????????????jupiterAccount.Withdraw(200);
160?????????????Console.WriteLine(jupiterAccount.ToString());
161?
162?????????????//?轉帳前
163?????????????ITransferBankAccount?currentAccount?=?new?CurrentAccount();
164?????????????currentAccount.PayIn(1000);
165?????????????Console.WriteLine(currentAccount.ToString());
166?????????????Console.WriteLine(venusAccount.ToString());
167?
168?????????????//?轉帳后
169?????????????currentAccount.TransferTo(venusAccount,?500);
170?????????????Console.WriteLine(currentAccount.ToString());
171?????????????Console.WriteLine(venusAccount.ToString());
172?
173?????????????Console.ReadKey();
174?????????}
175?????}
176?}
177?
178?
接口引用類似類的引用,但接口引用最大的好處是可以對所有實現了這個接口的所有類型進行操作。我們
不用擔心這個類是來做什么的,只要它實現了這個接口,我們就可以使用接口引用它,來進行接口指定的
操作。
洪虎
2006-10-2
轉載于:https://www.cnblogs.com/eric1394/archive/2006/10/02/520220.html
總結
- 上一篇: firefox图片不存在就显示小红叉的方
- 下一篇: SAPlink 的初次使用