【C#】Bookクラスを基本クラスとした場合の継承、ポリモーフィズムサンプル

C#でBookクラスがあった場合、その派生クラスとして適切なものをいくつか挙げます。Bookクラスが一般的な書籍の情報を保持するためのクラスであると仮定すると、その派生クラスとして以下のようなものが考えられます。

派生クラスの例

  1. EBook:電子書籍の特有の情報を保持するクラス。
  2. AudioBook:オーディオブックの特有の情報を保持するクラス。
  3. PrintedBook:印刷された書籍の特有の情報を保持するクラス。
  4. Textbook:教科書の特有の情報を保持するクラス。
  5. ComicBook:漫画やグラフィックノベルの特有の情報を保持するクラス。

継承

それぞれの派生クラスについて簡単なサンプルコードを示します。

// 基本のBookクラス
public class Book
{
    // タイトル
    public string Title { get; set; }

    // 著者
    public string Author { get; set; }

    // ページ数
    public int Pages { get; set; }

    // コンストラクタ
    public Book(string title, string author, int pages)
    {
        Title = title;
        Author = author;
        Pages = pages;
    }

    // 書籍情報を取得するメソッド
    public virtual string GetBookInfo()
    {
        return $"タイトル: {Title}, 著者: {Author}, ページ数: {Pages}";
    }
}

// EBookクラス - 電子書籍
public class EBook : Book
{
    // ファイルフォーマット(例:PDF, EPUB)
    public string FileFormat { get; set; }

    // ファイルサイズ(MB単位)
    public double FileSize { get; set; }

    // コンストラクタ
    public EBook(string title, string author, int pages, string fileFormat, double fileSize)
        : base(title, author, pages)
    {
        FileFormat = fileFormat;
        FileSize = fileSize;
    }

    // 電子書籍情報を取得するメソッド
    public override string GetBookInfo()
    {
        return $"{base.GetBookInfo()}, フォーマット: {FileFormat}, ファイルサイズ: {FileSize}MB";
    }
}

// AudioBookクラス - オーディオブック
public class AudioBook : Book
{
    // 再生時間(時間単位)
    public double Duration { get; set; }

    // ナレーター
    public string Narrator { get; set; }

    // コンストラクタ
    public AudioBook(string title, string author, int pages, double duration, string narrator)
        : base(title, author, pages)
    {
        Duration = duration;
        Narrator = narrator;
    }

    // オーディオブック情報を取得するメソッド
    public override string GetBookInfo()
    {
        return $"{base.GetBookInfo()}, 再生時間: {Duration}時間, ナレーター: {Narrator}";
    }
}

// PrintedBookクラス - 印刷された書籍
public class PrintedBook : Book
{
    // 出版社
    public string Publisher { get; set; }

    // ISBN番号
    public string ISBN { get; set; }

    // コンストラクタ
    public PrintedBook(string title, string author, int pages, string publisher, string isbn)
        : base(title, author, pages)
    {
        Publisher = publisher;
        ISBN = isbn;
    }

    // 印刷された書籍情報を取得するメソッド
    public override string GetBookInfo()
    {
        return $"{base.GetBookInfo()}, 出版社: {Publisher}, ISBN: {ISBN}";
    }
}

// Textbookクラス - 教科書
public class Textbook : Book
{
    // 科目(例:数学、科学)
    public string Subject { get; set; }

    // 学習レベル(例:高校、大学)
    public string Level { get; set; }

    // コンストラクタ
    public Textbook(string title, string author, int pages, string subject, string level)
        : base(title, author, pages)
    {
        Subject = subject;
        Level = level;
    }

    // 教科書情報を取得するメソッド
    public override string GetBookInfo()
    {
        return $"{base.GetBookInfo()}, 科目: {Subject}, レベル: {Level}";
    }
}

// ComicBookクラス - 漫画やグラフィックノベル
public class ComicBook : Book
{
    // イラストレーター
    public string Illustrator { get; set; }

    // シリーズ名
    public string Series { get; set; }

    // コンストラクタ
    public ComicBook(string title, string author, int pages, string illustrator, string series)
        : base(title, author, pages)
    {
        Illustrator = illustrator;
        Series = series;
    }

    // 漫画情報を取得するメソッド
    public override string GetBookInfo()
    {
        return $"{base.GetBookInfo()}, イラストレーター: {Illustrator}, シリーズ: {Series}";
    }
}
using System;

class Program
{
    static void Main()
    {
        // EBookの使用例
        EBook ebook = new EBook("C#プログラミング", "ジョン・ドウ", 300, "PDF", 5.2);
        Console.WriteLine(ebook.GetBookInfo());

        // AudioBookの使用例
        AudioBook audioBook = new AudioBook("C#を学ぶ", "ジェーン・スミス", 200, 10.5, "マイケル・ジョンソン");
        Console.WriteLine(audioBook.GetBookInfo());

        // PrintedBookの使用例
        PrintedBook printedBook = new PrintedBook("高度なC#", "エミリー・デイビス", 450, "テック出版社", "123-4567890123");
        Console.WriteLine(printedBook.GetBookInfo());

        // Textbookの使用例
        Textbook textbook = new Textbook("数学101", "アラン・チューリング博士", 350, "数学", "大学");
        Console.WriteLine(textbook.GetBookInfo());

        // ComicBookの使用例
        ComicBook comicBook = new ComicBook("スーパーC#ヒーローズ", "マーベル・スタジオ", 100, "スタン・リー", "シリーズ1");
        Console.WriteLine(comicBook.GetBookInfo());
    }
}

実行結果

このプログラムを実行すると、各クラスのGetBookInfoメソッドを使用して書籍情報を出力することができます。これにより、各クラスの特性を活かした情報取得が可能になります。

タイトル: C#プログラミング, 著者: ジョン・ドウ, ページ数: 300, フォーマット: PDF, ファイルサイズ: 5.2MB
タイトル: C#を学ぶ, 著者: ジェーン・スミス, ページ数: 200, 再生時間: 10.5時間, ナレーター: マイケル・ジョンソン
タイトル: 高度なC#, 著者: エミリー・デイビス, ページ数: 450, 出版社: テック出版社, ISBN: 123-4567890123
タイトル: 数学101, 著者: アラン・チューリング博士, ページ数: 350, 科目: 数学, レベル: 大学
タイトル: スーパーC#ヒーローズ, 著者: マーベル・スタジオ, ページ数: 100, イラストレーター: スタン・リー, シリーズ: シリーズ1

ポリモーフィズム

派生クラスのインスタンスをBook型の変数で宣言することもできます。これは、ポリモーフィズムの一例であり、基底クラスの型で派生クラスのインスタンスを扱うことができるためです。

以下に、Book型の変数を使用して派生クラスのインスタンスを作成する例を示します。

using System;

class Program
{
    static void Main()
    {
        // Book型の変数で宣言されたEBookのインスタンス
        Book ebook = new EBook("C#プログラミング", "ジョン・ドウ", 300, "PDF", 5.2);
        Console.WriteLine(ebook.GetBookInfo());

        // Book型の変数で宣言されたAudioBookのインスタンス
        Book audioBook = new AudioBook("C#を学ぶ", "ジェーン・スミス", 200, 10.5, "マイケル・ジョンソン");
        Console.WriteLine(audioBook.GetBookInfo());

        // Book型の変数で宣言されたPrintedBookのインスタンス
        Book printedBook = new PrintedBook("高度なC#", "エミリー・デイビス", 450, "テック出版社", "123-4567890123");
        Console.WriteLine(printedBook.GetBookInfo());

        // Book型の変数で宣言されたTextbookのインスタンス
        Book textbook = new Textbook("数学101", "アラン・チューリング博士", 350, "数学", "大学");
        Console.WriteLine(textbook.GetBookInfo());

        // Book型の変数で宣言されたComicBookのインスタンス
        Book comicBook = new ComicBook("スーパーC#ヒーローズ", "マーベル・スタジオ", 100, "スタン・リー", "シリーズ1");
        Console.WriteLine(comicBook.GetBookInfo());
    }
}

実行結果

タイトル: C#プログラミング, 著者: ジョン・ドウ, ページ数: 300, フォーマット: PDF, ファイルサイズ: 5.2MB
タイトル: C#を学ぶ, 著者: ジェーン・スミス, ページ数: 200, 再生時間: 10.5時間, ナレーター: マイケル・ジョンソン
タイトル: 高度なC#, 著者: エミリー・デイビス, ページ数: 450, 出版社: テック出版社, ISBN: 123-4567890123
タイトル: 数学101, 著者: アラン・チューリング博士, ページ数: 350, 科目: 数学, レベル: 大学
タイトル: スーパーC#ヒーローズ, 著者: マーベル・スタジオ, ページ数: 100, イラストレーター: スタン・リー, シリーズ: シリーズ1

Book型の変数で宣言された各インスタンスは、それぞれの派生クラス特有の情報を含むことができ、GetBookInfoメソッドを呼び出すと適切な情報が出力されます。これにより、ポリモーフィズムを利用して、基底クラス型の変数で派生クラスのインスタンスを扱うことが可能です。

メリット

  1. 柔軟性の向上:
    • 基底クラスの型で派生クラスのインスタンスを扱うことで、異なる派生クラスのオブジェクトを同じ方法で処理できます。これにより、コードの柔軟性が向上し、将来的に新しい派生クラスが追加された場合でも、既存のコードを大幅に変更する必要がなくなります。
  2. コードの簡素化:
    • 基底クラスの型で宣言された変数に派生クラスのオブジェクトを割り当てることで、同じ操作を複数の派生クラスに対して行う際に、条件分岐を減らすことができます。これにより、コードが簡潔で読みやすくなります。
  3. 一貫したインターフェースの提供:
    • 基底クラスに共通のメソッドを定義しておけば、派生クラスはそのメソッドをオーバーライドするだけで、同じインターフェースを提供できます。これにより、クライアントコードは基底クラスのメソッドを呼び出すだけで、具体的な派生クラスの実装を意識する必要がなくなります。
  4. 拡張性の確保:
    • 新しい派生クラスを追加する際に、既存の基底クラスのメソッドを再利用できるため、システムの拡張が容易になります。例えば、新しい種類の書籍を追加する場合でも、基底クラスのインターフェースを守ることで、既存の処理ロジックをそのまま利用できます。

具体例

例えば、以下のようにList<Book>を利用して、複数の派生クラスのインスタンスを同じリストで管理できます。

using System;
using System.Collections.Generic;

class Program
{
    static void Main()
    {
        // Book型のリストに複数の派生クラスのインスタンスを追加
        List<Book> books = new List<Book>
        {
            new EBook("C#プログラミング", "ジョン・ドウ", 300, "PDF", 5.2),
            new AudioBook("C#を学ぶ", "ジェーン・スミス", 200, 10.5, "マイケル・ジョンソン"),
            new PrintedBook("高度なC#", "エミリー・デイビス", 450, "テック出版社", "123-4567890123"),
            new Textbook("数学101", "アラン・チューリング博士", 350, "数学", "大学"),
            new ComicBook("スーパーC#ヒーローズ", "マーベル・スタジオ", 100, "スタン・リー", "シリーズ1")
        };

        // すべての書籍の情報を出力
        foreach (Book book in books)
        {
            Console.WriteLine(book.GetBookInfo());
        }
    }
}

このように、List<Book>を利用することで、異なる種類の書籍オブジェクトを一括で管理し、一貫した方法で情報を取得することができます。これにより、コードのメンテナンス性や拡張性が向上します。