物件導向程式設計(C#) - Microsoft Learn
文章推薦指數: 80 %
C# 提供物件導向程式設計的完整支援,包括抽象、封裝、繼承和多型。
跳到主要內容
已不再支援此瀏覽器。
請升級至MicrosoftEdge,以利用最新功能、安全性更新和技術支援。
下載MicrosoftEdge
其他資訊
目錄
結束焦點模式
閱讀英文
儲存
目錄
閱讀英文
儲存
Twitter
LinkedIn
Facebook
電子郵件
目錄
Object-Oriented程式設計(C#)
發行項
09/20/2022
3位參與者
本文內容
C#是物件導向的程式設計語言。
物件導向程式設計的四個基本準則如下:
抽象將實體的相關屬性和互動模型化為類別,以定義系統的抽象標記法。
封裝隱藏物件的內部狀態和功能,只允許透過公用函式集進行存取。
繼承能夠根據現有的抽象概念建立新的抽象概念。
多態性能夠跨多個抽象概念以不同方式實作繼承的屬性或方法。
在上述教學課程中,您同時看到抽象和封裝的類別簡介。
類別BankAccount提供銀行帳戶概念的抽象概念。
您可以修改其實作,而不會影響任何使用BankAccount類別的程式碼。
BankAccount和Transaction類別都提供在程式碼中描述這些概念所需的元件封裝。
在本教學課程中,您將擴充該應用程式,以利用繼承和多型來新增功能。
您也將將功能新增至BankAccount類別,利用您在上一個教學課程中學到的抽象概念和封裝技術。
建立不同類型的帳戶
建置此程式之後,您會收到將功能新增至此程式的要求。
在只有一個銀行帳戶類型的情況下,它很適合。
經過一段時間後,會要求變更和相關帳戶類型:
在每月結束時累算利息的利息收益帳戶。
信用額度可以有負數餘額,但當有餘額時,每個月會有利息費用。
以單一存單開頭的預先付費獎勵卡帳戶,只能支付費用。
您可以在每個月的開頭重新填入一次。
所有這些不同的帳戶都類似于BankAccount先前教學課程中所定義的類別。
您可以複製該程式碼、重新命名類別,並進行修改。
這項技術會在短期內運作,但一段時間後會有更多工作。
所有受影響的類別都會複製任何變更。
相反地,您可以建立新的銀行帳戶類型,從上一個教學課程中建立的BankAccount類別繼承方法和資料。
這些新類別可以使用每個類型所需的特定行為來擴充BankAccount類別:
publicclassInterestEarningAccount:BankAccount
{
}
publicclassLineOfCreditAccount:BankAccount
{
}
publicclassGiftCardAccount:BankAccount
{
}
每個類別都會繼承其共用基類的共用行為,也就是BankAccount類別。
針對每個衍生類別中的新功能和不同功能撰寫實作。
這些衍生類別已經有類別中BankAccount定義的所有行為。
最好在不同的原始程式檔中建立每個新類別。
在VisualStudio中,您可以以滑鼠右鍵按一下專案,然後選取[新增類別]以在新檔案中新增類別。
在VisualStudioCode中,選取[檔案]和[新增]以建立新的原始程式檔。
在任一工具中,將檔案命名為符合類別:InterestEarningAccount.cs、LineOfCreditAccount.cs和GiftCardAccount.cs。
當您建立如上述範例所示的類別時,您會發現不會編譯任何衍生類別。
建構函式負責初始化物件。
衍生類別建構函式必須初始化衍生類別,並提供如何初始化衍生類別中包含的基類物件的指示。
適當的初始化通常會在沒有任何額外程式碼的情況下發生。
類別BankAccount會宣告一個具有下列簽章的公用建構函式:
publicBankAccount(stringname,decimalinitialBalance)
當您自行定義建構函式時,編譯器不會產生預設建構函式。
這表示每個衍生類別都必須明確呼叫這個建構函式。
您可以宣告可將引數傳遞至基類建構函式的建構函式。
下列程式碼顯示的InterestEarningAccount建構函式:
publicInterestEarningAccount(stringname,decimalinitialBalance):base(name,initialBalance)
{
}
這個新建構函式的參數符合基類建構函式的參數類型和名稱。
您可以使用:base()語法來表示對基類建構函式的呼叫。
某些類別會定義多個建構函式,而且此語法可讓您挑選您呼叫的基類建構函式。
更新建構函式之後,您可以為每個衍生類別開發程式碼。
新類別的需求如下所述:
利息收益帳戶:
將會獲得2%的月份結束餘額點數。
信用額度:
可以有負數餘額,但絕對值不能大於信用額度。
將會在每個月產生利息費用,其中當月結束餘額不是0。
每個超過信用額度的退費都會產生費用。
一個獎勵卡帳戶:
可以在每個月的最後一天,以指定的金額重新填入一次。
您可以看到這三種帳戶類型都有一個動作,會在每個月結束時進行。
不過,每個帳戶類型都會執行不同的工作。
您可以使用多型來實作此程式碼。
在BankAccount類別中建立單virtual一方法:
publicvirtualvoidPerformMonthEndTransactions(){}
上述程式碼示範如何使用virtual關鍵字,在基類中宣告衍生類別可能提供不同實作的方法。
方法virtual是方法,其中任何衍生類別可以選擇重新實作。
衍生類別會使用override關鍵字來定義新的實作。
您通常會將此稱為「覆寫基類實作」。
關鍵字virtual指定衍生類別可能會覆寫行為。
您也可以宣告abstract衍生類別必須覆寫行為的方法。
基類不提供方法的abstract實作。
接下來,您必須定義您已建立之兩個新類別的實作。
InterestEarningAccount從開始:
publicoverridevoidPerformMonthEndTransactions()
{
if(Balance>500m)
{
decimalinterest=Balance*0.05m;
MakeDeposit(interest,DateTime.Now,"applymonthlyinterest");
}
}
將下列程式碼新增至LineOfCreditAccount。
此程式碼會否定餘額,以計算從帳戶撤銷的正利率費用:
publicoverridevoidPerformMonthEndTransactions()
{
if(Balance<0)
{
//Negatethebalancetogetapositiveinterestcharge:
decimalinterest=-Balance*0.07m;
MakeWithdrawal(interest,DateTime.Now,"Chargemonthlyinterest");
}
}
類別GiftCardAccount需要兩項變更,才能實作其月份結束功能。
首先,修改建構函式以包含每個月要新增的選擇性數量:
privatereadonlydecimal_monthlyDeposit=0m;
publicGiftCardAccount(stringname,decimalinitialBalance,decimalmonthlyDeposit=0):base(name,initialBalance)
=>_monthlyDeposit=monthlyDeposit;
建構函式會提供值的預設值,monthlyDeposit讓呼叫端可以省略0,而不需每月存金。
接下來,如果方法已設定為建構函式中的非零值,請覆寫PerformMonthEndTransactions方法以新增每月儲存:
publicoverridevoidPerformMonthEndTransactions()
{
if(_monthlyDeposit!=0)
{
MakeDeposit(_monthlyDeposit,DateTime.Now,"Addmonthlydeposit");
}
}
覆寫會在建構函式中套用每月儲存集。
將下列程式碼新增至方法,Main以測試和的InterestEarningAccount這些變更GiftCardAccount:
vargiftCard=newGiftCardAccount("giftcard",100,50);
giftCard.MakeWithdrawal(20,DateTime.Now,"getexpensivecoffee");
giftCard.MakeWithdrawal(50,DateTime.Now,"buygroceries");
giftCard.PerformMonthEndTransactions();
//canmakeadditionaldeposits:
giftCard.MakeDeposit(27.50m,DateTime.Now,"addsomeadditionalspendingmoney");
Console.WriteLine(giftCard.GetAccountHistory());
varsavings=newInterestEarningAccount("savingsaccount",10000);
savings.MakeDeposit(750,DateTime.Now,"savesomemoney");
savings.MakeDeposit(1250,DateTime.Now,"Addmoresavings");
savings.MakeWithdrawal(250,DateTime.Now,"Neededtopaymonthlybills");
savings.PerformMonthEndTransactions();
Console.WriteLine(savings.GetAccountHistory());
確認結果。
現在,為LineOfCreditAccount新增一組類似的測試程式碼:
varlineOfCredit=newLineOfCreditAccount("lineofcredit",0);
//Howmuchistoomuchtoborrow?
lineOfCredit.MakeWithdrawal(1000m,DateTime.Now,"Takeoutmonthlyadvance");
lineOfCredit.MakeDeposit(50m,DateTime.Now,"Paybacksmallamount");
lineOfCredit.MakeWithdrawal(5000m,DateTime.Now,"Emergencyfundsforrepairs");
lineOfCredit.MakeDeposit(150m,DateTime.Now,"Partialrestorationonrepairs");
lineOfCredit.PerformMonthEndTransactions();
Console.WriteLine(lineOfCredit.GetAccountHistory());
當您新增上述程式碼並執行程式時,您會看到類似下列錯誤的內容:
Unhandledexception.System.ArgumentOutOfRangeException:Amountofdepositmustbepositive(Parameter'amount')
atOOProgramming.BankAccount.MakeDeposit(Decimalamount,DateTimedate,Stringnote)inBankAccount.cs:line42
atOOProgramming.BankAccount..ctor(Stringname,DecimalinitialBalance)inBankAccount.cs:line31
atOOProgramming.LineOfCreditAccount..ctor(Stringname,DecimalinitialBalance)inLineOfCreditAccount.cs:line9
atOOProgramming.Program.Main(String[]args)inProgram.cs:line29
注意
實際輸出包含包含專案之資料夾的完整路徑。
為了簡潔起見,省略資料夾名稱。
此外,視您的程式碼格式而定,行號可能稍有不同。
此程式碼失敗,BankAccount因為假設初始餘額必須大於0。
另一個模擬到類別的BankAccount假設是餘額無法負數。
相反地,會拒絕過度繪製帳戶的任何撤銷。
這兩個假設都需要變更。
信用額度帳戶從0開始,而且通常會有負數餘額。
此外,如果客戶借用太多金錢,則會產生費用。
交易已接受,只需要花費更多成本。
第一個規則可以藉由將選擇性引數新增至指定最小平衡的建構函式來BankAccount實作。
預設值為0。
第二個規則需要一種機制,讓衍生類別能夠修改預設演算法。
事實上,基類會「詢問」衍生型別在發生超額時應該會發生什麼情況。
預設行為是擲回例外狀況來拒絕交易。
讓我們從新增包含選擇性minimumBalance參數的第二個建構函式開始。
這個新的建構函式會執行現有建構函式完成的所有動作。
此外,也會設定最小餘額屬性。
您可以複製現有建構函式的主體,但這表示未來要變更的兩個位置。
相反地,您可以使用建構函式鏈結讓一個建構函式呼叫另一個建構函式。
下列程式碼顯示兩個建構函式和新的額外欄位:
privatereadonlydecimal_minimumBalance;
publicBankAccount(stringname,decimalinitialBalance):this(name,initialBalance,0){}
publicBankAccount(stringname,decimalinitialBalance,decimalminimumBalance)
{
Number=s_accountNumberSeed.ToString();
s_accountNumberSeed++;
Owner=name;
_minimumBalance=minimumBalance;
if(initialBalance>0)
MakeDeposit(initialBalance,DateTime.Now,"Initialbalance");
}
上述程式碼顯示兩個新的技術。
首先,minimumBalance欄位會標示為readonly。
這表示在建構物件之後,無法變更值。
BankAccount建立之後,minimumBalance就無法變更。
其次,採用兩個參數的建構函式會做:this(name,initialBalance,0){}為其實作。
運算式:this()會呼叫另一個建構函式,也就是具有三個參數的建構函式。
雖然用戶端程式代碼可以選擇其中一個建構函式,但這項技術可讓您有單一實作來初始化物件。
只有在初始餘額大於0時,這個實作才會呼叫MakeDeposit。
這樣會保留存金必須是正數的規則,但可讓信用額度帳戶以餘額開啟0。
既然類別BankAccount具有最小平衡的唯讀欄位,最後一項變更就是將方法中的MakeWithdrawal硬式程式碼0minimumBalance變更為:
if(Balance-amount
如果撤銷未超過限制,此方法會傳null回交易。
這表示沒有費用。
將下列程式碼新增至Main類別中的Program方法,以測試這些變更:
varlineOfCredit=newLineOfCreditAccount("lineofcredit",0,2000);
//Howmuchistoomuchtoborrow?
lineOfCredit.MakeWithdrawal(1000m,DateTime.Now,"Takeoutmonthlyadvance");
lineOfCredit.MakeDeposit(50m,DateTime.Now,"Paybacksmallamount");
lineOfCredit.MakeWithdrawal(5000m,DateTime.Now,"Emergencyfundsforrepairs");
lineOfCredit.MakeDeposit(150m,DateTime.Now,"Partialrestorationonrepairs");
lineOfCredit.PerformMonthEndTransactions();
Console.WriteLine(lineOfCredit.GetAccountHistory());
執行程式,並檢查結果。
摘要
如果您遇到停滯,您可以在GitHub存放庫中看到本教學課程的來源。
本教學課程示範Object-Oriented程式設計中使用的許多技術:
當您為每個不同的帳戶類型定義類別時,使用了抽象概念。
這些類別描述該類型帳戶的行為。
當您在每個類別中保留許多詳細資料private時,使用了封裝。
當您利用類別中已建立的BankAccount實作來儲存程式碼時,使用了繼承。
當您建立virtual衍生類別的方法可以覆寫以建立該帳戶類型的特定行為時,您使用多型。
本文內容
延伸文章資訊
- 1物件導向程式設計 - 維基百科- Wikipedia
物件導向程式設計(英語:Object-oriented programming,縮寫:OOP)是種具有物件概念的程式設計典範,同時也是一種程式開發的抽象方針。它可能包含資料、特性、程式碼 ...
- 2物件導向程式設計
物件導向程式設計. Object Oriented Programming. 本章重點. ✪ 5-1 何謂物件(Object)? ✪ 5-2 類別的設計(Class Implement). ✪ ...
- 3Python基礎與物件導向程式設計| 誠品線上
Python基礎與物件導向程式設計:◇為前進人工智慧與物聯網相關技術的基礎學習課程。◇年輕化的內容風格,為應屆在學學生以及職訓學員學習量身打造的教學內容。
- 4初學者應該要知道的物件導向概念 - 快樂學程式
何謂物件導向傳統的程式設計主張將程式看作一系列函式的集合,或者直接就是一系列對電腦下達的指令,物件....
- 5物件導向程式設計篇 - HackMD
只要有心,Brainf*ck 語言也能作Object-Oriented Programming (OOP)! 摘自「無拘的物件導向」:. 如同數學上的複數,是由實數與虛數組合而成,而就物件 ...