Objektumorientált programozás felfedezése osztályokkal és objektumokkal
Ebben az oktatóanyagban egy konzolalkalmazást fog létrehozni, és megismerheti a C# nyelv részét képező alapvető objektumorientált funkciókat.
Előfeltételek
- A WindowsHoz készült Visual Studio használatát javasoljuk. Ingyenes verziót a Visual Studio letöltési oldaláról tölthet le. A Visual Studio tartalmazza a .NET SDK-t.
- A Visual Studio Code-szerkesztőt a C# DevKittel is használhatja. A legújabb .NET SDK-t külön kell telepítenie.
- Ha másik szerkesztőt szeretne, telepítenie kell a legújabb .NET SDK-t.
Az alkalmazás létrehozása
Terminálablak használatával hozzon létre egy Osztályok nevű könyvtárat. Ott fogja létrehozni az alkalmazást. Váltson erre a könyvtárra, és írja be dotnet new console
a konzolablakba. Ez a parancs létrehozza az alkalmazást. Nyissa meg a Program.cs fájlt. Ennek így kell kinéznie:
// See https://aka.ms/new-console-template for more information
Console.WriteLine("Hello, World!");
Ebben az oktatóanyagban olyan új típusokat fog létrehozni, amelyek egy bankszámlát jelölnek. A fejlesztők általában egy másik szövegfájlban definiálják az egyes osztályokat. Ez megkönnyíti a program méretének növekedésével való kezelését. Hozzon létre egy BankAccount.cs nevű új fájlt az Osztályok könyvtárban.
Ez a fájl tartalmazza a bankszámla definícióját. Az Objektumorientált programozás úgy rendszerezi a kódot, hogy osztályok formájában hoz létre típusokat. Ezek az osztályok egy adott entitást képviselő kódot tartalmaznak. Az BankAccount
osztály egy bankszámlát jelöl. A kód metódusokon és tulajdonságokon keresztül implementál bizonyos műveleteket. Ebben az oktatóanyagban a bankszámla támogatja ezt a viselkedést:
- 10 jegyű számmal rendelkezik, amely egyedileg azonosítja a bankszámlát.
- Van egy sztringje, amely a tulajdonosok nevét vagy nevét tárolja.
- Az egyenleg lekérhető.
- Elfogadja a betéteket.
- Elfogadja a visszavonásokat.
- A kezdeti egyenlegnek pozitívnak kell lennie.
- A kivonások nem eredményezhetnek negatív egyenleget.
A bankszámla típusának meghatározása
Először is létrehozhatja az adott viselkedést meghatározó osztály alapjait. Hozzon létre egy új fájlt a File:New paranccsal. Nevezze el BankAccount.cs. Adja hozzá a következő kódot a BankAccount.cs fájlhoz:
namespace Classes;
public class BankAccount
{
public string Number { get; }
public string Owner { get; set; }
public decimal Balance { get; }
public void MakeDeposit(decimal amount, DateTime date, string note)
{
}
public void MakeWithdrawal(decimal amount, DateTime date, string note)
{
}
}
Mielőtt továbblépnénk, tekintsük át, mit épített. A namespace
deklaráció lehetővé teszi a kód logikai rendszerezését. Ez az oktatóanyag viszonylag kicsi, ezért az összes kódot egy névtérbe helyezi.
public class BankAccount
A létrehozott osztályt vagy típust határozza meg. Az osztály deklarációját {
követő és }
azt követő összes elem meghatározza az osztály állapotát és viselkedését. Az osztálynak öt tagja BankAccount
van. Az első három tulajdonság. A tulajdonságok adatelemek, és olyan kódokkal rendelkezhetnek, amelyek érvényesítik az ellenőrzést vagy más szabályokat. Az utolsó kettő metódus. A metódusok olyan kódblokkok, amelyek egyetlen függvényt hajtanak végre. Az egyes tagok nevének olvasása elegendő információt nyújt Önnek vagy egy másik fejlesztőnek ahhoz, hogy megértse az osztályt.
Új fiók megnyitása
Az első implementálási funkció a bankszámla megnyitása. Amikor egy ügyfél megnyit egy fiókot, meg kell adnia egy kezdeti egyenleget, és információkat kell megadnia a fiók tulajdonosáról vagy tulajdonosairól.
A típus új objektumának BankAccount
létrehozása egy olyan konstruktor definiálását jelenti, amely hozzárendeli ezeket az értékeket. A konstruktor olyan tag, amelynek neve megegyezik az osztály nevével. Ez az osztálytípus objektumainak inicializálására szolgál. Adja hozzá a következő konstruktort a BankAccount
típushoz. Helyezze a következő kódot a következő deklaráció MakeDeposit
fölé:
public BankAccount(string name, decimal initialBalance)
{
this.Owner = name;
this.Balance = initialBalance;
}
Az előző kód a minősítővel this
azonosítja a létrehozandó objektum tulajdonságait. Ez a minősítő általában nem kötelező, és nincs megadva. A következőt is írhatta volna:
public BankAccount(string name, decimal initialBalance)
{
Owner = name;
Balance = initialBalance;
}
A this
minősítő csak akkor szükséges, ha egy helyi változó vagy paraméter neve megegyezik az adott mező vagy tulajdonság nevével. A this
minősítőt a cikk hátralévő részében kihagyjuk, hacsak nincs rá szükség.
A konstruktorok akkor lesznek meghívva, ha objektumot hoz létre a használatával new
. Cserélje le a Program.cs sorát Console.WriteLine("Hello World!");
a következő kódra (cserélje le <name>
a nevét):
using Classes;
var account = new BankAccount("<name>", 1000);
Console.WriteLine($"Account {account.Number} was created for {account.Owner} with {account.Balance} initial balance.");
Futtassuk le, amit eddig készített. Ha Visual Studiót használ, a Hibakeresés menüben hibakeresés nélkül válassza a Start lehetőséget. Ha parancssort használ, írja be dotnet run
azt a könyvtárat, amelyben létrehozta a projektet.
Észrevette, hogy a fiók száma üres? Itt az ideje, hogy ezt kijavítsuk. A fiókszámot az objektum létrehozásakor kell hozzárendelni. De nem a hívó feladata létrehozni. Az BankAccount
osztálykódnak tudnia kell, hogyan rendelhet hozzá új fiókszámokat. Egy egyszerű módszer egy 10 jegyű számmal kezdeni. Növekmény minden új fiók létrehozásakor. Végül tárolja az aktuális fiók számát egy objektum létrehozásakor.
Tagdeklaráció hozzáadása az BankAccount
osztályhoz. Helyezze a következő kódsort a nyitó zárójel {
után az BankAccount
osztály elejére:
private static int s_accountNumberSeed = 1234567890;
Ez accountNumberSeed
egy adattag. Ez private
azt jelenti, hogy csak az osztályon belüli BankAccount
kóddal érhető el. Ez a módszer elkülöníti a nyilvános felelősségeket (például egy fiókszámot) a magánvégrehajtástól (a fiókszámok létrehozásának módjától). Ez azt is static
jelenti, hogy az összes BankAccount
objektum megosztja. A nem statikus változók értéke egyedi az BankAccount
objektum minden példányára vonatkozóan. Ez accountNumberSeed
egy private static
mező, és így a C# elnevezési konvenciók szerint rendelkezik az s_
előtaggal. A s
denoting static
és _
denoting private
mező. Adja hozzá a következő két sort a konstruktorhoz a fiókszám hozzárendeléséhez. Helyezze őket a következő sor this.Balance = initialBalance
után:
Number = s_accountNumberSeed.ToString();
s_accountNumberSeed++;
Írja be dotnet run
az eredményeket.
Betétek és kivonások létrehozása
A megfelelő működéshez a bankszámlaosztálynak el kell fogadnia a befizetéseket és a kifizetéseket. Alkalmazzuk a betéteket és a kifizetéseket úgy, hogy létrehozunk egy naplót a fiók minden tranzakciójának. Az egyes tranzakciók nyomon követése számos előnnyel jár az egyes tranzakciók egyenlegének egyszerű frissítésével szemben. Az előzmények az összes tranzakció naplózására és a napi egyenlegek kezelésére használhatók. Ha szükség van rá, az összes tranzakció előzményeiből származó egyenleg kiszámítása biztosítja, hogy egy rögzített tranzakció hibái megfelelően tükröződnek a következő számítás egyenlegében.
Először hozzunk létre egy új típust, amely egy tranzakciót jelöl. A tranzakció egy egyszerű típus, amely nem rendelkezik felelősségekkel. Szüksége van néhány tulajdonságra. Hozzon létre egy Transaction.cs nevű új fájlt. Adja hozzá a következő kódot:
namespace Classes;
public class Transaction
{
public decimal Amount { get; }
public DateTime Date { get; }
public string Notes { get; }
public Transaction(decimal amount, DateTime date, string note)
{
Amount = amount;
Date = date;
Notes = note;
}
}
Most adjunk hozzá egy List<T> Transaction
objektumot az BankAccount
osztályhoz. Adja hozzá a következő deklarációt a konstruktor után a BankAccount.cs fájlban:
private List<Transaction> _allTransactions = new List<Transaction>();
Most számítsuk ki helyesen a Balance
. Az aktuális egyenleg az összes tranzakció értékeinek összegzésével érhető el. A kód jelenleg csak a fiók kezdeti egyenlegét tudja lekérni, ezért frissítenie kell a tulajdonságot Balance
. Cserélje le a BankAccount.cs sorát public decimal Balance { get; }
a következő kódra:
public decimal Balance
{
get
{
decimal balance = 0;
foreach (var item in _allTransactions)
{
balance += item.Amount;
}
return balance;
}
}
Ez a példa a tulajdonságok egy fontos aspektusát mutatja be. Most már kiszámítja az egyenleget, amikor egy másik programozó kéri az értéket. A számítás az összes tranzakciót számba adja, és az aktuális egyenlegként adja meg az összeget.
Ezután implementálja a módszereket és MakeWithdrawal
a MakeDeposit
módszereket. Ezek a módszerek kényszerítik az utolsó két szabályt: a kezdeti egyenlegnek pozitívnak kell lennie, és a visszavonás nem hozhat létre negatív egyenleget.
Ezek a szabályok a kivételek fogalmát vezetik be. Egy metódus nem tudja sikeresen befejezni a munkáját, ha kivételt küld. A kivétel típusa és a hozzá társított üzenet írja le a hibát. Ebben az esetben a MakeDeposit
metódus kivételt jelez, ha a betét összege nem nagyobb 0-nál. A MakeWithdrawal
módszer kivételt eredményez, ha a visszavonási összeg nem nagyobb 0-nál, vagy ha a visszavonás alkalmazása negatív egyenleget eredményez. Adja hozzá a következő kódot a _allTransactions
lista deklarációja után:
public void MakeDeposit(decimal amount, DateTime date, string note)
{
if (amount <= 0)
{
throw new ArgumentOutOfRangeException(nameof(amount), "Amount of deposit must be positive");
}
var deposit = new Transaction(amount, date, note);
_allTransactions.Add(deposit);
}
public void MakeWithdrawal(decimal amount, DateTime date, string note)
{
if (amount <= 0)
{
throw new ArgumentOutOfRangeException(nameof(amount), "Amount of withdrawal must be positive");
}
if (Balance - amount < 0)
{
throw new InvalidOperationException("Not sufficient funds for this withdrawal");
}
var withdrawal = new Transaction(-amount, date, note);
_allTransactions.Add(withdrawal);
}
Az throw
utasítás kivételt jelez . Az aktuális blokk végrehajtása véget ér, és a hívásverem első egyező catch
blokkjára irányuló átvitel vezérlése. Egy blokkot catch
fog hozzáadni a kód teszteléséhez egy kicsit később.
A konstruktornak egyetlen módosítást kell kapnia, hogy egy kezdeti tranzakciót adjon hozzá ahelyett, hogy közvetlenül frissítenék az egyenleget. Mivel már megírta a metódust MakeDeposit
, hívja a konstruktortól. A kész konstruktornak így kell kinéznie:
public BankAccount(string name, decimal initialBalance)
{
Number = s_accountNumberSeed.ToString();
s_accountNumberSeed++;
Owner = name;
MakeDeposit(initialBalance, DateTime.Now, "Initial balance");
}
DateTime.Now egy tulajdonság, amely az aktuális dátumot és időpontot adja vissza. Tesztelje ezt a kódot úgy, hogy hozzáad néhány befizetést és kifizetést a Main
metódushoz, az új BankAccount
kódot létrehozó kódot követve:
account.MakeWithdrawal(500, DateTime.Now, "Rent payment");
Console.WriteLine(account.Balance);
account.MakeDeposit(100, DateTime.Now, "Friend paid me back");
Console.WriteLine(account.Balance);
Következő lépésként tesztelje, hogy hibafeltételeket fog-e észlelni, ha negatív egyenlegű fiókot próbál létrehozni. Adja hozzá a következő kódot az imént hozzáadott kód után:
// Test that the initial balances must be positive.
BankAccount invalidAccount;
try
{
invalidAccount = new BankAccount("invalid", -55);
}
catch (ArgumentOutOfRangeException e)
{
Console.WriteLine("Exception caught creating account with negative balance");
Console.WriteLine(e.ToString());
return;
}
Az utasítással try-catch
megjelölhet egy kódblokkot, amely kivételeket okozhat, és észlelheti a várt hibákat. Ugyanezzel a technikával tesztelheti azt a kódot, amely kivételt eredményez egy negatív egyenleg esetében. Adja hozzá a következő kódot a metódus deklarációja invalidAccount
Main
előtt:
// Test for a negative balance.
try
{
account.MakeWithdrawal(750, DateTime.Now, "Attempt to overdraw");
}
catch (InvalidOperationException e)
{
Console.WriteLine("Exception caught trying to overdraw");
Console.WriteLine(e.ToString());
}
Mentse a fájlt, és írja be dotnet run
a kipróbálásához.
Kihívás – az összes tranzakció naplózása
Az oktatóanyag befejezéséhez megírhatja azt a GetAccountHistory
metódust, amely létrehoz egy string
tranzakciós előzményeket. Adja hozzá ezt a metódust a BankAccount
következő típushoz:
public string GetAccountHistory()
{
var report = new System.Text.StringBuilder();
decimal balance = 0;
report.AppendLine("Date\t\tAmount\tBalance\tNote");
foreach (var item in _allTransactions)
{
balance += item.Amount;
report.AppendLine($"{item.Date.ToShortDateString()}\t{item.Amount}\t{balance}\t{item.Notes}");
}
return report.ToString();
}
Az előzmények az StringBuilder osztály használatával formáznak egy sztringet, amely minden tranzakcióhoz egy sort tartalmaz. Az oktatóanyagokban korábban már láthatta a sztringformázási kódot. Az egyik új karakter a .\t
Ez beszúr egy lapot a kimenet formázásához.
Adja hozzá ezt a sort a Program.cs teszteléséhez:
Console.WriteLine(account.GetAccountHistory());
Futtassa a programot az eredmények megtekintéséhez.
Következő lépések
Ha elakadt, az oktatóanyag forrását a GitHub-adattárban tekintheti meg.
Folytathatja az objektumorientált programozási oktatóanyagot.
Ezekről a fogalmakról az alábbi cikkekben tudhat meg többet: