C#でのオブジェクト指向学習サンプル1(レジ基本)
スーパーのレジシステムをコンソールアプリでシミュレートして、オブジェクト指向のメリットをみていきましょう
オブジェクト指向の初学では、オブジェクト指向の書き方も大切ですが、まず、何がメリットなのか、なぜ使うのか、自分が理解しやすい例えで学習しているかに着目して進めるといいでしょう
無闇に時間をかけるより、イメージを掴むように心がけましょう
実行結果
お客(山田さん)が買い物かごに買いたい商品を入れていきます
必要なものを入れたらレジで精算(レシート表示)します
手続型でいいのでは?
この実行結果からコードを書くとすると手続型(変数、条件分岐、繰り返し)でシンプルにコードが書けますし、特に難しく感じないと思った方も多いでしょう
今回の学習の着地となるイメージ
基本のサンプルが動かないと話にならないので、山田さんだけがお客のように見えるものになっていますが、他のお客にも対応できるようにすることを想定することが大事ですね(レジですから・・・)
次のコードは難しく感じると思いますが、バラバラにお客がやってきて購入し、バラバラにレジで精算する様子を表しています
さらにお客を増やすこともできそうですね
手続型ではお客が増えると同じようにしようとするとごちゃごちゃすることが想定できます
・・・頑張って、手続型でコードを書いてみますか??? >> 大変そうですね
// レジオブジェクトを作成
Reg reg1 = new Reg();
// 山田さんを作成
Customer customer1 = new Customer("山田");
Customer customer2 = new Customer("森本");
Customer customer3 = new Customer("太田");
// 森本さんが先に購入
customer2.Buy();
// 森本さんがそのまま清算
reg1.PrintReceipt(customer2);
customer1.Buy();
customer3.Buy();
reg1.PrintReceipt(customer3);
reg1.PrintReceipt(customer1);
イメージ
クラス図
上記のイメージを図式で表したものになります
イラストはありませんが、各クラス名、属性名(フィールド名)、振る舞い名(メソッド名)が記されています
四角形は3段に分かれている上段がクラス名(©️はクラスを表します)、中段が属性、下段が振る舞いを表しています
メソッドの()内は引数になります
分析の方法
UMLのクラス図を習得されていないことを前提に説明します
レジシステム(全体のコントロール)で、お客とレジのインスタンスを作成しています
Runメソッドには、お客がアイテムを購入することとレジでレシートを表示するよう指示されています
お客は、複数のアイテムを購入することができます
また、レジを使うことができます
ここで使うとは、レジのレシート表示メソッドを呼び出すことを指します
creates
インスタンスの作成を指します
has
持っている様子(保持、コンポジション)を指します
uses
利用することを表します
シーケンス図
このシーケンス図では、Program
クラスがRegSystem
のRun()
メソッドを呼び出すことで、Customer
クラスのインスタンスを作成し、Buy()
メソッドを呼び出して買い物の情報を入力します。その後、Reg
クラスのPrintReceipt()
メソッドを呼び出してレシートを表示しています。
アクティビティ図
このアクティビティ図は、次のようなフローを表しています。
- プログラムが開始すると、顧客インスタンスが作成されます(
Customer
クラスのコンストラクタ呼び出し)。 - 顧客は商品の数を入力します(
Buy
メソッド内のループで商品名と価格が入力されます)。 - 入力された商品情報をもとに、レジシステムが実行されます(
RegSystem
クラスのRun
メソッド内で顧客のインスタンスを作成し、Reg
クラスのPrintReceipt
メソッドでレシートを表示)。 - レシートが表示され、プログラムが終了します。
コード
C#の初学であれば、次のポイントに注意して確認してください
クラスは中を2つの部分に分けて分析してみます
属性(データ、フィールドともいいます)と振る舞い(動作の部分でメソッドや関数とも言います)の2つです
メソッドは、ブロック内を全て理解することを目的にせず、メソッド名から何の動作をさせようとしているのかを分析対象とします
Item.cs
商品クラスになります
属性
商品名と価格の2つで考えます
振る舞い
商品名と価格を表示するのみになります
// Itemクラス(設計図)
/// <summary>
/// スーパーの商品クラス
/// </summary>
class Item
{
// (フィールド)
// 商品名
public string name;
// 価格
public int price;
// ------------------------------------
// (メソッド、関数、プロシジャー、ファンクション)
// 商品名と価格を表示する
public void Show()
{
Console.WriteLine($"{name}の価格は{price}円です");
}
}
Customer.cs
お客クラスになります
商品を複数持っていることを表しています
属性
お客様名と複数の商品の2つで考えます
振る舞い
インスタンス作成時名前を登録すると購入するの2つになります
class Customer
{
public string name;
// カートの商品
public Item[] items;
public Customer(string name)
{
this.name = name;
}
public void Buy()
{
// Itemクラス(設計図)からインスタンスを作成する(オブジェクトを作成)
// =>インスタンス化ともいいます
// 商品の数を入力する
Console.Write($"{name}さんの買い物かごの商品の数は? ");
int itemCount = int.Parse(Console.ReadLine());
items = new Item[itemCount];
for (int i = 0; i < itemCount; i++)
{
Console.Write("商品名: ");
string itemName = Console.ReadLine();
Console.Write("価格: ");
int itemPrice = int.Parse(Console.ReadLine());
items[i] = new Item { name = itemName, price = itemPrice };
}
}
}
Reg.cs
レジクラスになります
属性
ありません
レシートが記されていますが、表示用のため今回は考えなくていいでしょう
振る舞い
レシートを表示するのみになります
class Reg
{
// レシートを表示する
public void PrintReceipt(Customer customer)
{
Console.WriteLine($"{customer.name}さんのレシート");
Console.WriteLine("----------------------------");
// レシートの表示
for (int i = 0; i < customer.items.Length; i++)
{
// 商品名を表示する
Console.WriteLine($"商品{i + 1}: {customer.items[i].name} {customer.items[i].price}円");
}
// 合計金額を入れる変数を用意する
int totalPrice = 0;
// 商品の数だけ繰り返す
for (int i = 0; i < customer.items.Length; i++)
{
// 合計金額に商品の価格を足していく
totalPrice += customer.items[i].price;
}
Console.WriteLine("----------------------------");
// 合計を表示する
Console.WriteLine($"合計金額は{totalPrice}円です");
}
}
RegSystem.cs
レジのシステム全体をコントロールするクラスになります
属性
ありません
振る舞い
Runメソッドからコードが始まります
ここでは、お客様の山田さんの作成、買い物をする、レジの作成、レシートを表示するを行なっています
class RegSystem
{
public void Run()
{
Customer customer1 = new Customer("山田");
customer1.Buy();
Reg reg1 = new Reg();
reg1.PrintReceipt(customer1);
}
}
Program.cs
C#でプログラムが実行される最初のメソッドになります
属性
ありません
振る舞い
ここでは、レジシステムの作成、レジの実行を行なっています
RegSystem regSystem = new RegSystem();
regSystem.Run();
おまけ
PlantUML記法
@startuml
class Program{
-Main()
}
class RegSystem {
+ Run()
}
class Customer {
- name: string
- items: Item[]
+ Customer(name: string)
+ Buy()
}
class Item {
- name: string
- price: int
+ Show()
}
class Reg {
+ PrintReceipt(customer: Customer)
}
Program --> RegSystem : creates
RegSystem --> Customer : creates
RegSystem --> Reg : creates
Customer "1" --> "*" Item : has
Customer --> Reg : uses
@enduml
@startuml
actor Customer
Program -> RegSystem: new RegSystem()
Program -> RegSystem: Run()
RegSystem -> Customer: new Customer("山田")
Customer -> Customer: Buy()
Customer -> Console: "山田さんの買い物かごの商品の数は?"
Console -> Customer: itemCount
loop itemCount
Customer -> Console: "商品名:"
Console -> Customer: itemName
Customer -> Console: "価格:"
Console -> Customer: ItemPrice
Customer -> Item: new Item(itemName, ItemPrice)
end
Customer -> Customer: items = Item[]
RegSystem -> Reg: new Reg()
Reg -> Reg: PrintReceipt(customer1)
Reg -> Console: "山田さんのレシート"
Reg -> Console: "----------------------------"
loop customer1.items.Length
Reg -> Console: "商品i + 1: " + customer1.items[i].name + " " + customer1.items[i].price + "円"
end
Reg -> Reg: totalPrice = 0
loop customer1.items.Length
Reg -> Reg: totalPrice += customer1.items[i].price
end
Reg -> Console: "----------------------------"
Reg -> Console: "合計金額は" + totalPrice + "円です"
@enduml
@startuml
skinparam shadowing false
start
:顧客インスタンスを作成;
:買い物かごの商品数を入力;
while (商品数 > 0)
:商品名を入力;
:価格を入力;
endwhile
:レジシステムを実行;
:レシートを表示;
stop
@enduml
ディスカッション
コメント一覧
まだ、コメントがありません