オブジェクト指向プログラミング (C#)Object-Oriented programming (C#)

C# はオブジェクト指向言語です。C# is an object-oriented language. オブジェクト指向プログラミングで使用される 4 つの主要な手法は次のとおりです。Four of the key techniques used in object-oriented programming are:

  • "抽象化" とは、型コンシューマーから不要な詳細を隠すことです。Abstraction means hiding the unnecessary details from type consumers.
  • "カプセル化" とは、関連するプロパティ、メソッド、およびその他のメンバーのグループが 1 つの単位またはオブジェクトとして扱われることを意味します。Encapsulation means that a group of related properties, methods, and other members are treated as a single unit or object.
  • "継承" は、既存のクラスに基づいて新しいクラスを作成する機能です。Inheritance describes the ability to create new classes based on an existing class.
  • "ポリモーフィズム" とは、同じプロパティまたはメソッドを異なる方法で実装している複数のクラスを、交換して使用できることです。Polymorphism means that you can have multiple classes that can be used interchangeably, even though each class implements the same properties or methods in different ways.

前のチュートリアルのクラスの概要では、"抽象化" と "カプセル化" の両方について説明しました。In the preceding tutorial, introduction to classes you saw both abstraction and encapsulation. BankAccount クラスによって、銀行口座の概念に対する抽象化が提供されました。The BankAccount class provided an abstraction for the concept of a bank account. その実装は、BankAccount クラスを使用したコードのいずれにも影響を与えずに変更できました。You could modify its implementation without affecting any of the code that used the BankAccount class. BankAccountTransaction クラスの両方で、これらの概念をコードで記述するために必要なコンポーネントのカプセル化が提供されます。Both the BankAccount and Transaction classes provide encapsulation of the components needed to describe those concepts in code.

このチュートリアルでは、このアプリケーションを拡張し、"継承" と "ポリモーフィズム" を使用して新機能を追加します。In this tutorial, you'll extend that application to make use of inheritance and polymorphism to add new features. また、前のチュートリアルで学習した "抽象化" と "カプセル化" の手法を活用して、BankAccount クラスに機能を追加します。You'll also add features to the BankAccount class, taking advantage of the abstraction and encapsulation techniques you learned in the preceding tutorial.

さまざまな種類の口座を作成するCreate different types of accounts

このプログラムを構築した後、あなたは機能を追加するように要求されます。After building this program, you get requests to add features to it. これは、銀行口座の種類が 1 つしかない場合に適しています。It works great in the situation where there is only one bank account type. 時間の経過と共に、ニーズが変化し、関連する口座の種類が要求されます。Over time, needs change, and related account types are requested:

  • 月末ごとに利息がつく、利息つき口座。An interest earning account that accrues interest at the end of each month.
  • 残高が負の値になる可能性のある与信枠。ただし、残高がある場合は、毎月利息を請求されます。A line of credit that can have a negative balance, but when there's a balance, there's an interest charge each month.
  • 前払いのギフト カード口座。1 回の預金で始まり、支払いのみが可能です。A pre-paid gift card account that starts with a single deposit, and only can be paid off. 毎月初めに 1 回補充できます。It can be refilled once at the start of each month.

これらの各種口座はすべて、前のチュートリアルで定義した BankAccount クラスに似ています。All of these different accounts are similar to BankAccount class defined in the earlier tutorial. そのコードをコピーし、クラスの名前を変更して、変更を加えることができます。You could copy that code, rename the classes, and make modifications. この手法は短期的にはうまくいきますが、時間の経過と共に作業量が多くなります。That technique would work in the short term, but it would be more work over time. あらゆる変更を、影響を受けるすべてのクラス間でコピーする必要があります。Any changes would be copied across all the affected classes.

代わりに、前のチュートリアルで作成した BankAccount クラスからメソッドとデータを継承する、新しい銀行口座の種類を作成できます。Instead, you can create new bank account types that inherit methods and data from the BankAccount class created in the preceding tutorial. これらの新しいクラスでは、各種類に必要な特定の動作で BankAccount クラスを拡張できます。These new classes can extend the BankAccount class with the specific behavior needed for each type:

public class InterestEarningAccount : BankAccount
{
}

public class LineOfCreditAccount : BankAccount
{
}

public class GiftCardAccount : BankAccount
{
}

これらの各クラスは、共有の "基底クラス" である BankAccount クラスから、共有の動作を "継承" します。Each of these classes inherits the shared behavior from their shared base class, the BankAccount class. その "派生クラス" ごとに、新しい異なる機能の実装を記述します。Write the implementations for new and different functionality in each of the derived classes. これらの派生クラスには、BankAccount クラスで定義されているすべての動作が既に備わっています。These derived classes already have all the behavior defined in the BankAccount class.

新しいクラスは、それぞれ別のソース ファイルに作成することをお勧めします。It's a good practice to create each new class in a different source file. Visual Studio では、プロジェクトを右クリックして [クラスの追加] を選択すると、新しいファイルに新しいクラスを追加できます。In Visual Studio, you can right-click on the project, and select add class to add a new class in a new file. Visual Studio Code では、 [ファイル][新規] の順に選択すると新しいソース ファイルを作成できます。In Visual Studio Code, select File then New to create a new source file. どちらのツールでも、クラスと一致するようにファイル名を指定します。InterestEarningAccount.csLineOfCreditAccount.csGiftCardAccount.cs です。In either tool, name the file to match the class: InterestEarningAccount.cs, LineOfCreditAccount.cs, and GiftCardAccount.cs.

前述のサンプルのようなクラスを作成すると、どの派生クラスもコンパイルされないことがわかります。When you create the classes as shown in the preceding sample, you'll find that none of your derived classes compile. コンストラクターによって、オブジェクトの初期化が行われます。A constructor is responsible for initializing an object. 派生クラスのコンストラクターでは、派生クラスを初期化し、その派生クラスに含まれる基底クラスのオブジェクトを初期化する方法を指定する必要があります。A derived class constructor must initialize the derived class, and provide instructions on how to initialize the base class object included in the derived class. 通常、適切な初期化は追加のコードなしで行われます。The proper initialization normally happens without any extra code. BankAccount クラスでは、次のシグネチャを持つ 1 つのパブリック コンストラクターが宣言されます。The BankAccount class declares one public constructor with the following signature:

public BankAccount(string name, decimal initialBalance)

コンストラクターを自分で定義した場合、コンパイラによって既定のコンストラクターが生成されることはありません。The compiler doesn't generate a default constructor when you define a constructor yourself. これは、各派生クラスで明示的にこのコンストラクターを呼び出す必要があることを意味します。That means each derived class must explicitly call this constructor. 基底クラスのコンストラクターに引数を渡すことができるコンストラクターを宣言します。You declare a constructor that can pass arguments to the base class constructor. 次のコードは、InterestEarningAccount のコンストラクターを示しています。The following code shows the constructor for the InterestEarningAccount:

public InterestEarningAccount(string name, decimal initialBalance) : base(name, initialBalance) 
{ 
}

この新しいコンストラクターのパラメーターは、基底クラスのコンストラクターのパラメーターと型と名前が一致しています。The parameters to this new constructor match the parameter type and names of the base class constructor. : base() 構文を使用して、基底クラスのコンストラクターへの呼び出しを示すことができます。You use the : base() syntax to indicate a call to a base class constructor. 複数のコンストラクターを定義するクラスもあります。この構文を使用することで、呼び出す基底クラスのコンストラクターを選択できます。Some classes define multiple constructors, and this syntax enables you to pick which base class constructor you call. コンストラクターを更新したら、各派生クラスのコードを開発できます。Once you've updated the constructors, you can develop the code for each of the derived classes. 新しいクラスの要件は、次のように記述できます。The requirements for the new classes can be stated as follows:

  • 利息つき口座:An interest earning account:
    • 月末の残高の 2% が振り込まれます。Will get a credit of 2% of the month-ending-balance.
  • 与信枠:A line of credit:
    • 残高を負の値にすることができますが、与信限度額よりも絶対値を大きくすることはできません。Can have a negative balance, but not be greater in absolute value than the credit limit.
    • 月末の残高が 0 ではない場合は、毎月利息を請求されます。Will incur an interest charge each month where the end of month balance isn't 0.
    • 与信限度額を超えた引き出しごとに手数料が発生します。Will incur a fee on each withdrawal that goes over the credit limit.
  • ギフト カード口座:A gift card account:
    • 毎月 1 回、月の最終日に指定した金額を補充できます。Can be refilled with a specified amount once each month, on the last day of the month.

これら 3 種類の口座には、すべて月末ごとに実行されるアクションがあることがわかります。You can see that all three of these account types have an action that takes places at the end of each month. ただし、口座の種類ごとに異なるタスクが実行されます。However, each account type does different tasks. このコードを実装するために、"ポリモーフィズム" を使用します。You use polymorphism to implement this code. BankAccount クラスで 1 つの virtual メソッドを作成します。Create a single virtual method in the BankAccount class:

public virtual void PerformMonthEndTransactions() { }

前のコードでは、virtual キーワードを使用して、派生クラスで異なる実装を提供できる基底クラスのメソッドを宣言する方法を示しています。The preceding code shows how you use the virtual keyword to declare a method in the base class that a derived class may provide a different implementation for. virtual メソッドは、任意の派生クラスで再実装することを選択できるメソッドです。A virtual method is a method where any derived class may choose to reimplement. 派生クラスでは、override キーワードを使用して新しい実装を定義します。The derived classes use the override keyword to define the new implementation. 通常、これは "基底クラスの実装のオーバーライド" と呼ばれます。Typically you refer to this as "overriding the base class implementation". virtual キーワードによって、派生クラスで動作をオーバーライドする可能性があることを指定できます。The virtual keyword specifies that derived classes may override the behavior. また、派生クラスで動作をオーバーライドしなければならない abstract メソッドを宣言することもできます。You can also declare abstract methods where derived classes must override the behavior. 基底クラスでは abstract メソッドの実装が提供されません。The base class does not provide an implementation for an abstract method. 次に、作成した 2 つの新しいクラスの実装を定義する必要があります。Next, you need to define the implementation for two of the new classes you've created. まずは InterestEarningAccount です。Start with the InterestEarningAccount:

public override void PerformMonthEndTransactions()
{
    if (Balance > 500m)
    {
        var interest = Balance * 0.05m;
        MakeDeposit(interest, DateTime.Now, "apply monthly interest");
    }
}

LineOfCreditAccount に次のコードを追加します。Add the following code to the LineOfCreditAccount. このコードでは、残高の符号を反転させて、口座から引き出される正の利息請求額を計算しています。The code negates the balance to compute a positive interest charge that is withdrawn from the account:

public override void PerformMonthEndTransactions()
{
    if (Balance < 0)
    {
        // Negate the balance to get a positive interest charge:
        var interest = -Balance * 0.07m;
        MakeWithdrawal(interest, DateTime.Now, "Charge monthly interest");
    }
}

GiftCardAccount クラスには、月末の機能を実装するために 2 つの変更が必要です。The GiftCardAccount class needs two changes to implement its month-end functionality. 最初に、毎月追加できる省略可能な金額を含めるようにコンストラクターを変更します。First, modify the constructor to include an optional amount to add each month:

private decimal _monthlyDeposit = 0m;

public GiftCardAccount(string name, decimal initialBalance, decimal monthlyDeposit = 0) : base(name, initialBalance)
    => _monthlyDeposit = monthlyDeposit;

このコンストラクターでは monthlyDeposit の値に対して既定値が指定されています。これにより、毎月の預金がない場合に呼び出し元は 0 を省略できます。The constructor provides a default value for the monthlyDeposit value so callers can omit a 0 for no monthly deposit. 次に、PerformMonthEndTransactions メソッドをオーバーライドして、毎月の預金がコンストラクターで 0 以外の値に設定されていた場合にそれを追加するようにします。Next, override the PerformMonthEndTransactions method to add the monthly deposit, if it was set to a non-zero value in the constructor:

public override void PerformMonthEndTransactions()
{
    if (_monthlyDeposit != 0)
    {
        MakeDeposit(_monthlyDeposit, DateTime.Now, "Add monthly deposit");
    }
}

このオーバーライドにより、コンストラクターで設定された毎月の預金が適用されます。The override applies the monthly deposit set in the constructor. 次のコードを Main メソッドに追加して、GiftCardAccountInterestEarningAccount に対するこれらの変更内容をテストします。Add the following code to the Main method to test these changes for the GiftCardAccount and the InterestEarningAccount:

var giftCard = new GiftCardAccount("gift card", 100, 50);
giftCard.MakeWithdrawal(20, DateTime.Now, "get expensive coffee");
giftCard.MakeWithdrawal(50, DateTime.Now, "buy groceries");
giftCard.PerformMonthEndTransactions();
// can make additional deposits:
giftCard.MakeDeposit(27.50m, DateTime.Now, "add some additional spending money");
Console.WriteLine(giftCard.GetAccountHistory());

var savings = new InterestEarningAccount("savings account", 10000);
savings.MakeDeposit(750, DateTime.Now, "save some money");
savings.MakeDeposit(1250, DateTime.Now, "Add more savings");
savings.MakeWithdrawal(250, DateTime.Now, "Needed to pay monthly bills");
savings.PerformMonthEndTransactions();
Console.WriteLine(savings.GetAccountHistory());

結果を確認しましょう。Verify the results. 次に、LineOfCreditAccount に対して類似した一連のテスト コードを追加します。Now, add a similar set of test code for the LineOfCreditAccount:

var lineOfCredit = new LineOfCreditAccount("line of credit", 0, 2000);
// How much is too much to borrow?
lineOfCredit.MakeWithdrawal(1000m, DateTime.Now, "Take out monthly advance");
lineOfCredit.MakeDeposit(50m, DateTime.Now, "Pay back small amount");
lineOfCredit.MakeWithdrawal(5000m, DateTime.Now, "Emergency funds for repairs");
lineOfCredit.MakeDeposit(150m, DateTime.Now, "Partial restoration on repairs");
lineOfCredit.PerformMonthEndTransactions();
Console.WriteLine(lineOfCredit.GetAccountHistory());

上記のコードを追加してプログラムを実行すると、次のようなエラーが表示されます。When you add the preceding code and run the program, you'll see something like the following error:

Unhandled exception. System.ArgumentOutOfRangeException: Amount of deposit must be positive (Parameter 'amount')
   at OOProgramming.BankAccount.MakeDeposit(Decimal amount, DateTime date, String note) in BankAccount.cs:line 42
   at OOProgramming.BankAccount..ctor(String name, Decimal initialBalance) in BankAccount.cs:line 31
   at OOProgramming.LineOfCreditAccount..ctor(String name, Decimal initialBalance) in LineOfCreditAccount.cs:line 9
   at OOProgramming.Program.Main(String[] args) in Program.cs:line 29

注意

実際の出力には、プロジェクトを含むフォルダーへの完全なパスが含まれています。The actual output includes the full path to the folder with the project. 簡潔にするため、フォルダー名は省略されています。The folder names were omitted for brevity. また、コード形式によっては、行番号が若干異なる場合があります。Also, depending on your code format, the line numbers may be slightly different.

このコードが失敗したのは、BankAccount によって初期残高は 0 より大きいと仮定されているためです。This code fails because the BankAccount assumes that the initial balance must be greater than 0. BankAccount クラスに織り込まれているもう 1 つの前提は、残高を負の値にすることはできないということです。Another assumption baked into the BankAccount class is that the balance can't go negative. 代わりに、口座残高を超える引き出しは拒否されます。Instead, any withdrawal that overdraws the account is rejected. これらの前提はどちらも変更する必要があります。Both of those assumptions need to change. 与信枠口座は 0 から始まり、通常は残高が負になります。The line of credit account starts at 0, and generally will have a negative balance. また、顧客がお金を借りすぎた場合、手数料が発生します。Also, if a customer borrows too much money, they incur a fee. そのトランザクションは承認されます。追加料金がかかるだけです。The transaction is accepted, it just costs more. 最初の規則は、最小残高を指定する省略可能な引数を BankAccount コンストラクターに追加することによって実装できます。The first rule can be implemented by adding an optional argument to the BankAccount constructor that specifies the minimum balance. 既定では、 0です。The default is 0. 2 番目の規則には、派生クラスで既定のアルゴリズムを変更できるようにするメカニズムが必要です。The second rule requires a mechanism that enables derived classes to modify the default algorithm. ある意味では、基底クラスが派生型に、過剰な引き出しがあった場合にどうするかを "尋ね" ます。In a sense, the base class "asks" the derived type what should happen when there's an overdraft. 既定の動作では、例外をスローすることによってトランザクションを拒否します。The default behavior is to reject the transaction by throwing an exception.

まず、省略可能な minimumBalance パラメーターを含む 2 番目のコンストラクターを追加しましょう。Let's start by adding a second constructor that includes an optional minimumBalance parameter. この新しいコンストラクターでは、既存のコンストラクターで実行されるすべてのアクションが実行されます。This new constructor does all the actions done by the existing constructor. さらに、最小残高のプロパティも設定されます。Also, it sets the minimum balance property. 既存のコンストラクターの本体をコピーすることもできます。You could copy the body of the existing constructor. ただし、今後は 2 か所を変更しなければならなくなります。but that means two locations to change in the future. 代わりに、"コンストラクター チェーン" を使用して、1 つのコンストラクターが別のコンストラクターを呼び出すようにすることができます。Instead, you can use constructor chaining to have one constructor call another. 次のコードは、2 つのコンストラクターと新しい追加フィールドを示しています。The following code shows the two constructors and the new additional field:

private readonly decimal minimumBalance;

public BankAccount(string name, decimal initialBalance) : this(name, initialBalance, 0) { }

public BankAccount(string name, decimal initialBalance, decimal minimumBalance)
{
    this.Number = accountNumberSeed.ToString();
    accountNumberSeed++;

    this.Owner = name;
    this.minimumBalance = minimumBalance;
    if (initialBalance > 0)
        MakeDeposit(initialBalance, DateTime.Now, "Initial balance");
}

上記のコードには、2 つの新しい手法が示されています。The preceding code shows two new techniques. まず、minimumBalance フィールドは readonly としてマークされています。First, the minimumBalance field is marked as readonly. これは、オブジェクトを構築した後はこの値を変更できないことを意味します。That means the value cannot be changed after the object is constructed. BankAccount の作成後に minimumBalance を変更することはできません。Once a BankAccount is created, the minimumBalance can't change. 次に、2 つのパラメーターを受け取るコンストラクターでは、実装として : this(name, initialBalance, 0) { } が使用されています。Second, the constructor that takes two parameters uses : this(name, initialBalance, 0) { } as its implementation. : this() 式によって、3 つのパラメーターを持つ別のコンストラクターを呼び出します。The : this() expression calls the other constructor, the one with three parameters. この手法を使用すると、オブジェクトを初期化するための実装を 1 つ用意して、クライアント コードでは多数のコンストラクターの中からいずれかを選択できるようにすることができます。This technique allows you to have a single implementation for initializing an object even though client code can choose one of many constructors.

この実装では、初期残高が 0 よりも大きい場合にのみ MakeDeposit が呼び出されます。This implementation calls MakeDeposit only if the initial balance is greater than 0. これにより、預金は正である必要があるという規則を守りつつ、残高 0 で与信枠口座を開設することができます。That preserves the rule that deposits must be positive, yet lets the credit account open with a 0 balance.

これで BankAccount クラスに最小残高用の読み取り専用フィールドが設定されたので、最後の変更として、MakeWithdrawal メソッドのハードコーディングされた 0minimumBalance に変更します。Now that the BankAccount class has a read-only field for the minimum balance, the final change is to change the hard code 0 to minimumBalance in the MakeWithdrawal method:

if (Balance - amount < minimumBalance)

BankAccount クラスを拡張した後、次のコードに示すように、新しい基底コンストラクターを呼び出すように LineOfCreditAccount コンストラクターを変更できます。After extending the BankAccount class, you can modify the LineOfCreditAccount constructor to call the new base constructor, as shown in the following code:

public LineOfCreditAccount(string name, decimal initialBalance, decimal creditLimit) : base(name, initialBalance, -creditLimit)
{
}

LineOfCreditAccount コンストラクターでは、minimumBalance パラメーターの意味と一致するように、creditLimit パラメーターの符号が変更されることがわかります。Notice that the LineOfCreditAccount constructor changes the sign of the creditLimit parameter so it matches the meaning of the minimumBalance parameter.

過剰な引き出しに対する異なる規則Different overdraft rules

追加する最後の機能により、LineOfCreditAccount で、与信限度額の超過に対してトランザクションを拒否するのではなく、手数料を請求できるようになります。The last feature to add enables the LineOfCreditAccount to charge a fee for going over the credit limit instead of refusing the transaction.

1 つの手法は、必要な動作を実装する仮想関数を定義することです。One technique is to define a virtual function where you implement the required behavior. Bank Account クラスでは、MakeWithdrawal メソッドが 2 つのメソッドにリファクターされます。The Bank Account class refactors the MakeWithdrawal method into two methods. 新しいメソッドでは、引き出しによって残高が最小値を下回る場合に、指定されたアクションが実行されます。The new method does the specified action when the withdrawal takes the balance below the minimum. 既存の MakeWithdrawal メソッドには、次のコードが含まれています。The existing MakeWithdrawal method has the following code:

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 < minimumBalance)
    {
        throw new InvalidOperationException("Not sufficient funds for this withdrawal");
    }
    var withdrawal = new Transaction(-amount, date, note);
    allTransactions.Add(withdrawal);
}

見つかったコードを次のコードと置き換えます。Replace it with the following code:

public void MakeWithdrawal(decimal amount, DateTime date, string note)
{
    if (amount <= 0)
    {
        throw new ArgumentOutOfRangeException(nameof(amount), "Amount of withdrawal must be positive");
    }
    var overdraftTransaction = CheckWithdrawalLimit(Balance - amount < minimumBalance);
    var withdrawal = new Transaction(-amount, date, note);
    allTransactions.Add(withdrawal);
    if (overdraftTransaction != null)
        allTransactions.Add(overdraftTransaction);
}

protected virtual Transaction? CheckWithdrawalLimit(bool isOverdrawn)
{
    if (isOverdrawn)
    {
        throw new InvalidOperationException("Not sufficient funds for this withdrawal");
    }
    else
    {
        return default;
    }
}

追加されたメソッドは protected です。これは、派生クラスからのみ呼び出せることを意味します。The added method is protected, which means that it can be called only from derived classes. この宣言によって、他のクライアントがこのメソッドを呼び出せなくなります。That declaration prevents other clients from calling the method. これは virtual でもあるため、派生クラスで動作を変更できます。It's also virtual so that derived classes can change the behavior. 戻り値の型は Transaction? です。The return type is a Transaction?. ? の注釈は、メソッドが null を返す可能性があることを示します。The ? annotation indicates that the method may return null. 次の実装を LineOfCreditAccount に追加して、引き出しの限度額を超えたときに手数料を請求します。Add the following implementation in the LineOfCreditAccount to charge a fee when the withdrawal limit is exceeded:

protected override Transaction? CheckWithdrawalLimit(bool isOverdrawn) =>
    isOverdrawn
    ? new Transaction(-20, DateTime.Now, "Apply overdraft fee")
    : default;

このオーバーライドでは、残高が過剰に引き出された場合に手数料のトランザクションが返されます。The override returns a fee transaction when the account is overdrawn. 引き出しが限度額を超えていない場合は、メソッドから null トランザクションが返されます。If the withdrawal doesn't go over the limit, the method returns a null transaction. これは手数料が発生していないことを示します。That indicates there's no fee. Program クラスの Main メソッドに次のコードを追加して、これらの変更をテストします。Test these changes by adding the following code to your Main method in the Program class:

var lineOfCredit = new LineOfCreditAccount("line of credit", 0, 2000);
// How much is too much to borrow?
lineOfCredit.MakeWithdrawal(1000m, DateTime.Now, "Take out monthly advance");
lineOfCredit.MakeDeposit(50m, DateTime.Now, "Pay back small amount");
lineOfCredit.MakeWithdrawal(5000m, DateTime.Now, "Emergency funds for repairs");
lineOfCredit.MakeDeposit(150m, DateTime.Now, "Partial restoration on repairs");
lineOfCredit.PerformMonthEndTransactions();
Console.WriteLine(lineOfCredit.GetAccountHistory());

プログラムを実行し、結果を確認します。Run the program, and check the results.

まとめSummary

このチュートリアルでは、オブジェクト指向プログラミングで使用される多くの手法を示しました。This tutorial demonstrated many of the techniques used in Object-Oriented programming:

  • 各クラスで多くの詳細情報を private にしたとき、"抽象化" を使用しました。You used Abstraction when you kept many details private in each class.
  • 異なる種類の口座ごとにクラスを定義したとき、"カプセル化" を使用しました。You used Encapsulation when you defined classes for each of the different account types. これらのクラスによって、その種類の口座の動作が記述されました。Those classes described the behavior for that type of account.
  • BankAccount クラスに既に作成されている実装を活用してコードを節約したとき、"継承" を使用しました。You used Inheritance when you leveraged the implementation already created in the BankAccount class to save code.
  • 派生クラスでオーバーライドしてその口座の種類に固有の動作を作成できる virtual メソッドを作成したとき、"ポリモーフィズム" を使用しました。You used Polymorphism when you created virtual methods that derived classes could override to create specific behavior for that account type.

お疲れさまでした。これで、C# の概要に関する全チュートリアルを完了しました。Congratulations, you've finished all of our introduction to C# tutorials. さらに学習する場合は、その他のチュートリアルをお試しください。To learn more, try more of our tutorials.