C#でのオブジェクト指向学習サンプル2(レジ、マイナスの商品は買えないようにする)

2023年7月28日

C#でのオブジェクト指向学習サンプル1(レジ基本)で、基本的なレジをシミュレートしてみました
まだ確認されていない方は、これから進めてください

ベースとなる基本レジ

シンプルで、これはこれでいいと思いますが、さらに現実のレジに近づけてみましょう

新たに実現したい機能

商品の値段にマイナスを入力されることは現実的ではありません
今回はこれをなんとかしようとします

機能を単純にするため、今回はマイナスが入力されても0に変更されるようにします

レジ基本の実行結果

お客(山田さん)が買い物かごに買いたい商品を入れていきます
必要なものを入れたらレジで精算(レシート表示)します

レジ、マイナス商品は買えないようにするの実行結果

同様な処理で料金にマイナスを入力しています

コード

C#の初学であれば、次のポイントに注意して確認してください

クラスは中を2つの部分に分けて分析してみます

属性(データ、フィールドともいいます)と振る舞い(動作の部分でメソッドや関数とも言います)の2つです

メソッドは、ブロック内を全て理解することを目的にせず、メソッド名から何の動作をさせようとしているのかを分析対象とします

Item.cs

商品クラスになります

属性

商品名価格の2つで考えます

振る舞い

商品名と価格を表示するのみになります

// Itemクラス(設計図)
/// <summary>
/// スーパーの商品クラス
/// </summary>
class Item
{
    // (フィールド)
    // 商品名
    public string name;

    // 価格
    // このクラス外からはアクセスできないフィールド(private修飾子)
    private int price;

    // (プロパティ)public修飾子なのでクラス外からアクセスできる
    public int Price
    {
        get
        {
            // 読み込まれた場合の処理
            return price;
        }
        set
        {
            // 書き込まれた場合の処理
            if (value < 0)
            {
                price = 0;
            }
            else
            {
                price = value;
            }
        }
    }

    // ------------------------------------

    // (メソッド、関数、プロシジャー、ファンクション)
    // 商品名と価格を表示する
    public void Show()
    {
        Console.WriteLine($"{name}の価格は{price}円です");
    }
}

条件によって内部のデータを守ります(保護されます)

書き込み側サンプル(Priceプロパティに代入する)
Item item = new Item();
item.Price = -100;
書き込まれるプロパティ

書き込まれる場合、プロパティのset側のブロックが実行されます
書き込まれるデータ(今回は-100)は、valueという特別な変数に代入されます

ブロック内のif文で、valueは0より小さいので、priceには0が代入されることになります

ここで、PriceとpriceはC#では別変数扱いになることに注意してください

public int Price
{
    get
    {
        // 読み込まれた場合の処理
        return price;
    }
    set
    {
        // 書き込まれた場合の処理
        if (value < 0)
        {
            price = 0;
        }
        else
        {
            price = value;
        }
    }
}

Customer.cs

プロパティ化で、値段にアクセスする場合、price変数だったところをPrice変数に変更します

お客クラスになります
商品を複数持っていることを表しています

属性

お客様名複数の商品の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

プロパティ化で、値段にアクセスする場合、price変数だったところをPrice変数に変更します

レジクラスになります

属性

ありません

レシートが記されていますが、表示用のため今回は考えなくていいでしょう

振る舞い

レシートを表示するのみになります

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
    + Price : int
    + Show() : void
}
}

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