講義メモ

提出フォロー:アレンジ演習:p.240 inheritance05.cs

・派生クラスのオーバーライドメソッドを、そのまま、派生の派生クラスでオーバーライドできることを確認しよう
・Derived2クラスを継承するDerived3クラスを定義して、Show()メソッドをオーバーライドし、Main()で呼び出てみよう

作成例

//アレンジ演習:p.240 inheritance05.cs
using System;
class MyBase { //基本クラス
    protected int x = 10; //継承可能なインスタンス変数
    public virtual void show() { //仮想メソッド
        Console.WriteLine("x = {0}", x);
    }
}
class Derived1 : MyBase { //派生クラス
    // ここに「protected int x = 10; //継承可能なインスタンス変数」が継承される
    protected int y = 20; //継承可能なインスタンス変数
    // ここに「public virtual void show() … //仮想メソッド」が継承される
}
class Derived2 : Derived1 { //派生の派生クラス
    // ここに「protected int x = 10; //継承可能なインスタンス変数」が継承される
    // ここに「protected int y = 20; //継承可能なインスタンス変数」が継承される
    int z = 30; //継承されないインスタンス変数
    // ここに「public virtual void show() … //仮想メソッド」が継承されるがオーバライドされる
    public override void show() { //オーバライドメソッド
        Console.WriteLine("z = {0}", z);
    }
}
class Derived3 : Derived2 { //【以下追加】派生の派生の派生クラス
    // ここに「protected int x = 10; //継承可能なインスタンス変数」が継承される
    // ここに「protected int y = 20; //継承可能なインスタンス変数」が継承される
    // ここに「public virtual void show() … //仮想メソッド」が継承されるがオーバライドされる
    public override void show() { //オーバライドメソッド
        Console.WriteLine("x = {0}, y = {1}", x, y);
    }
}
class inheritance05 {
    public static void Main() {
        MyBase mb; //基本クラス型の変数
        Derived1 d1 = new Derived1(); //派生クラスのインスタンス
        Derived2 d2 = new Derived2(); //派生の派生クラスのインスタンス
        mb = d1; //派生クラスのインスタンスを基本クラス型で扱う
        mb.show(); //オーバライドなので多態性が発動し派生クラスのメソッドを実行
        mb = d2; //派生の派生クラスのインスタンスを基本クラス型で扱う
        mb.show(); //オーバライドなので多態性が発動し派生クラスのメソッドを実行
        //【以下追加】
        Derived2 d3 = new Derived3(); //派生の派生の派生クラスのインスタンス
        d3.show(); //オーバライドメソッドを実行
    }
}

p.243 クラスの継承とコンストラクタ

・どのクラスにおいても、コンストラクタ(p.167)を記述しないと、自動的に引数のないコンストラクタが用意される
・これは派生クラスでも同様
・しかし、派生クラスのコンストラクタの前には自動的に基本クラスのコンストラクタが実行される
・これにより、基本クラスから継承したデータメンバの初期化を基本クラスのコンストラクタに任させることができる
・基本クラスに引数を持つコンストラクタがあり、派生クラスにも引数を持つコンストラクタがある場合、引数を受け渡す必要があるので、
 baseキーワードを用いる
・書式: public 派生クラス名(型 引数,…) : base (受け取りたい引数,…) {…}

p.243 inheritance06.cs

//p.243 inheritance06.cs
using System;
class MyBase { //基本クラス
    protected int x; //継承可能なインスタンス変数
    public MyBase() { //④基本クラスの引数無コンストラクタ
        Console.WriteLine("ここはMyBase"); //⑤
        x = 10; //⑥
    }
}
class Derived1 : MyBase { //派生クラス
    public Derived1() { //③派生クラスの引数無コンストラクタ
        //ここで基本クラスの引数無コンストラクタが実行される
        Console.WriteLine("ここはDerived1"); //⑦
        x = 20; //⑧
    }
}
class Derived2 : Derived1 { //派生の派生クラス
    public Derived2() { //②派生の派生クラスの引数無コンストラクタ
        //ここで派生クラスの引数無コンストラクタが実行される(その中で基本クラスの引数無コンストラクタが実行される)
        Console.WriteLine("ここはDerived2"); //⑨
        x = 30; //⑩
    }
    public void show() { //⑫自前のメソッド
        Console.WriteLine("x = {0}", x); //⑬
    }
}
class inheritance06 {
    public static void Main() {
        Derived2 d2 = new Derived2(); //①派生の派生オブジェクトを生成&コンストラクタを呼ぶ
        d2.show(); //⑪派生の派生オブジェクトのメソッドを呼ぶ
    }
}

アレンジ演習:p.243 inheritance06.cs

・Derived1クラスにprivateなint型のインスタンス変数yを追加
・また、yに40を代入し、その旨を表示する処理をコンストラクタに追加

作成例

//アレンジ演習:p.243 inheritance06.cs
using System;
class MyBase { //基本クラス
    protected int x; //継承可能なインスタンス変数
    public MyBase() { //④基本クラスの引数無コンストラクタ
        Console.WriteLine("ここはMyBase"); //⑤
        x = 10; //⑥
    }
}
class Derived1 : MyBase { //派生クラス
    private int y;
    public Derived1() { //③派生クラスの引数無コンストラクタ
        //ここで基本クラスの引数無コンストラクタが実行される
        Console.WriteLine("ここはDerived1"); //⑦
        x = 20; //⑧
        Console.WriteLine("yに40を代入"); //【追加】
        y = 40; //【追加】
    }
}
class Derived2 : Derived1 { //派生の派生クラス
    public Derived2() { //②派生の派生クラスの引数無コンストラクタ
        //ここで派生クラスの引数無コンストラクタが実行される(その中で基本クラスの引数無コンストラクタが実行される)
        Console.WriteLine("ここはDerived2"); //⑨
        x = 30; //⑩
    }
    public void show() { //⑫自前のメソッド
        Console.WriteLine("x = {0}", x); //⑬
    }
}
class inheritance06 {
    public static void Main() {
        Derived2 d2 = new Derived2(); //①派生の派生オブジェクトを生成&コンストラクタを呼ぶ
        d2.show(); //⑪派生の派生オブジェクトのメソッドを呼ぶ
    }
}

アレンジ演習:p.245 inheritance07.cs

・テキストp.246下から4行目の例のとおりに、コンストラクタを書換え、呼び出し部分などもアレンジしてみよう

作成例

//アレンジ演習:p.245 inheritance07.cs
using System;
class MyBase { //基本クラス
    protected double d; //継承可能なインスタンス変数
    public MyBase(double a, double b, double c) { //基本クラスの引数有コンストラクタ
        d = Math.Pow(b, 2.0) - 4.0 * a * c; //判別式の値を返す
    }
}
class MyJudge : MyBase { //派生クラス
    public bool bJudge; //内部用のフラグ変数
    public MyJudge(int x, double p, double q, string str, double r) //【変更】派生クラスの引数有コンストラクタ
        : base(p, q, r) { //MyBaseクラスのコンストラクタに引数を渡す
        //ここで基本クラスの引数有コンストラクタが実行される(引数は↑から受け取る)
        Console.WriteLine("判別式 = {0}", d); //基本クラスの引数有コンストラクタによりdに代入
        if (d < 0.0) {
            bJudge = false;
        } else {
            bJudge = true;
        }
        Console.WriteLine("x = {0}, str = {1}", x, str); //【追加】基本クラスの引数有コンストラクタによりdに代入
    }
}
class inheritance07 {
    public static void Main() {
        MyJudge mj = new MyJudge(100, 1.0, 2.0, "OK", 3.0); //【変更】コンストラクタに5値を渡す
        Console.WriteLine(mj.bJudge);
        MyJudge mk = new MyJudge(200, 1.0, 4.0, "NG", 0.0); //【変更】コンストラクタに5値を渡す
        Console.WriteLine(mk.bJudge);
    }
}

p.247 抽象クラス:補足

・p.256にある通り、抽象メソッドと同様に、抽象プロパティ、抽象インデクサを記述できる
・抽象プロパティの書式: abstruct 戻り値型 プロパティ名{get; set;}; //getとsetのどちらかは省略可
・抽象インデクサの書式: abstruct 戻り値型 this[インデクス型 インデクス名]{get; set;}; //getとsetのどちらかは省略可

p.248 abstract01.cs

//p.248 abstract01.cs
using System;
abstract class MyAb { //抽象クラスMyAb
    public abstract double Hanbetsu(double a, double b, double c); //抽象メソッド
}
class MyHanbetsu : MyAb { //MyAbの派生クラス
    //ここに「public abstract double Hanbetsu(double a, double b, double c);」があるとみなされる
    public override double Hanbetsu(double a, double b, double c) { //↑のオーバライド
        return Math.Pow(b, 2.0) - 4.0 * a * c;
    }
}
class abstract01 {
    public static void Main() {
        //MyAb y = new MyAb(); //【確認】抽象クラスのインスタンスは生成不可
        MyHanbetsu h = new MyHanbetsu(); //派生クラスのインスタンスを生成
        double d = h.Hanbetsu(1.0, 2.0, 3.0); //オーバライドメソッドを実行
        Console.WriteLine(d);
    }
}

アレンジ演習:p.248 abstruct01.cs

・抽象クラスMyAbに抽象プロパティage(戻り値型:int、get/set有)を追加する
・すると、MyHanbetuクラスが抽象クラスになり、そのままではエラーになる
・そこで、MyHanbetuクラスの派生クラスYourHanbetuを追記し、抽象プロパティageをオーバーライドしよう
・そして、Mainメソッドにおいて、派生クラスYourHanbetuを使うようしてエラーを解消しよう

作成例

//アレンジ演習:p.248 abstract01.cs
using System;
abstract class MyAb { //抽象クラスMyAb
    public abstract double Hanbetsu(double a, double b, double c); //抽象メソッド
    public abstract int age { get; set;} //【追加】抽象プロパティ 
}
abstract class MyHanbetsu : MyAb { //【変更】MyAbの派生抽象クラス
    //ここに抽象メソッド「public abstract double Hanbetsu(double a, double b, double c);」があるとみなされる
    public override double Hanbetsu(double a, double b, double c) { //↑のオーバライド
        return Math.Pow(b, 2.0) - 4.0 * a * c;
    }
    //ここに抽象プロパティ「public abstract int age { get; set;}」があるとみなされる
}
class YourHanbetsu : MyHanbetsu { //【以下追加】派生の派生クラス
    int yourage = 0;
    //ここに抽象メソッド「public abstract double Hanbetsu(double a, double b, double c);」があるとみなされる
    //ここにオーバライド「public override double Hanbetsu(double a, double b, double c) {}」があるとみなされる
    //ここに抽象プロパティ「public abstract int age { get; set;}」があるとみなされる
    public override int age { get { return yourage; }  set { yourage = value;} } //↑のオーバライド
}
class abstract01 {
    public static void Main() {
        //MyHanbetsu h = new MyHanbetsu(); //【削除】派生クラスのインスタンスを生成
        YourHanbetsu h = new YourHanbetsu(); //【差替】派生の派生クラスのインスタンスを生成
        double d = h.Hanbetsu(1.0, 2.0, 3.0); //オーバライドメソッドを実行
        Console.WriteLine(d);
        Console.WriteLine(h.age); //【追加】オーバーライドプロパティを呼ぶ
    }
}

p.249 抽象クラス:sealedクラスについて

・抽象クラスとは逆の概念で、継承を禁止するにはsealedクラスにすると良い
・継承は便利だが、publicメンバが無条件に引き継がれてしまうので、これを避けたい場合に用いる
・なお、C#が提供するクラスの中にも、sealedクラスがあり、継承しようとするとエラーになる
 sealedクラスの例: Stringクラス、Int32クラス、など
 sealedではないクラスの例:System.Collections.ArrayListクラス(p.177) など
・ちなみに、静的クラス(p.204)も継承できない

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です