講義メモ

・p.266「インターフェイスの継承」から(※ 9章の練習問題も行います)

提出フォロー:ミニ演習 mini266.cs

・「アレンジ演習:p.265 interface05.cs」からIDaインターフェイスを除外して、動作を確認しよう

作成例

//ミニ演習 mini266.cs
using System;
interface IMas { //「です・ます」を示すインターフェイス
    void show(int i); //抽象メソッド①
}
abstract class Base { //抽象クラス
    public abstract void show(int i); //抽象メソッド②
}
class MyClass : Base, IMas { //抽象クラスを継承しインターフェイスを実装するクラス
    void IMas.show(int i) { //抽象メソッド①のオーバライドなので「です・ます」
        Console.WriteLine("iは{0}です", i);
    }
    public override void show(int i) { //抽象メソッド②のオーバライド
        Console.WriteLine("iは{0}", i);
    }
}
class interface05 {
    public static void Main() {
        IMas im; //インターフェイス型の変数
        MyClass mc = new MyClass(); //抽象クラスを継承しインターフェイスを実装するクラスのオブジェクト
        im = mc; //インターフェイス型の変数に代入して
        im.show(5); //抽象メソッド①のオーバライドを実行
        mc.show(5); //インターフェイス型の変数を経由しないと抽象メソッド②のオーバライドを実行
    }
}

p.266 インターフェイスの継承

・クラスの継承と同様に、インターフェイスをインターフェイスが継承できる
・これにより、インターフェイスの乱立を防ぐことができる
・また、あるインターフェイスで定義済の抽象メンバを、他のインターフェイスでも定義してしまうことも防止できる。
・継承されるインターフェイスを基本インターフェイス、継承するインターフェイスを派生インターフェイスという
・定義書式: interface 派生インターフェイス : 基本インターフェイス {…}
・なお、継承なので、派生インターフェイスが複数の基本インターフェイスを持つことはできない

p.266 interface06.cs

//p.266 interface06.cs
using System;
interface IInterface1 { //基本インターフェイス
    void setdatano(int n); //抽象メソッド①
    void setdata(double data, int i); //抽象メソッド②
    double calcsum(); //抽象メソッド③
}
interface IInterface2 : IInterface1 { //派生インターフェイス
    //ここに「void setdatano(int n); //抽象メソッド①」があるとみなす
    //ここに「void setdata(double data, int i); //抽象メソッド②」があるとみなす
    //ここに「double calcsum(); //抽象メソッド③」があるとみなす
    double calcaverage(); //抽象メソッド④
}
class MyClass : IInterface2 { //派生インターフェイスを実装するクラス
    double[] data; //配列用の参照変数
    bool bOK = false; //生成済フラグをオフにする
    public void setdatano(int n) { //抽象メソッド①のオーバライド
        data = new double[n]; //引数で受け取った要素数の配列を生成
        bOK = true; //生成済フラグをオンにする
    }
    public void setdata(double d, int i) { //抽象メソッド②のオーバライド
        if (!bOK) { //生成済フラグがオフ(未生成)?
            Console.WriteLine("配列の準備ができていません");
            return;
        }
        data[i] = d; //引数で受け取った値と添字で配列に格納
    }
    public double calcsum() { //抽象メソッド③のオーバライド
        if (!bOK) { //生成済フラグがオフ(未生成)?
            Console.WriteLine("配列の準備ができていません");
            return -1.0; //未済である旨を返す
        }
        double sum = 0.0; //合計用
        for (int i = 0; i < data.Length; i++) { //全データについて繰返す
            sum += data[i]; //合計に足し込む
        }
        return sum; //合計を返す
    }
    public double calcaverage() { //抽象メソッド④のオーバライド
        double sum = calcsum(); //合計を得る
        return sum / data.Length; //件数で割って平均を得て返す
    }
}
class interface06 {
    public static void Main() {
        MyClass mc = new MyClass();
        int nNo;
        while (true) { //無限ループ
            Console.Write("データ数---");
            string strno = Console.ReadLine();
            nNo = Int32.Parse(strno); //「int.Parse」と同じ
            mc.setdatano(nNo); //要素数nNoの配列を生成
            for (int i = 0; i < nNo; i++) { //要素数の分、繰返す
                Console.Write("data[{0}] = ", i);
                string strdata = Console.ReadLine();
                mc.setdata(double.Parse(strdata), i); //順に格納
            }
            Console.WriteLine("合計 = {0}", mc.calcsum());
            Console.WriteLine("平均 = {0}", mc.calcaverage());
            Console.WriteLine();
            Console.Write("続けますか(Y/N)---");
            string yn = Console.ReadLine();
            if (yn == "N" || yn == "n") {
                break;
            }
        }
    }
}

ミニ演習 mini267.cs

・派生インターフェイスを型とする変数を、基本インターフェイスを型とする変数で扱えるかどうか確認しよう
・基本インターフェイス: interface RunAble { void run(); }
・派生インターフェイス: interface FastRunAble { void fastrun(); }
・派生インターフェイスを実装するクラス: class Dragon : FastRunAble {…}

作成例

//ミニ演習 mini267.cs
using System;
interface RunAble { //基本インターフェイス
    void run(); //抽象メソッド①
}
interface FastRunAble  : RunAble { //派生インターフェイス
    //ここに「void run();//抽象メソッド①」があるとみなす
    void fastrun(); //抽象メソッド②
}
class Dragon : FastRunAble { //派生インターフェイスを実装するクラス
    public void run() { //抽象メソッド①のオーバライド
        Console.WriteLine("脚で走る");
    }
    public void fastrun() { //抽象メソッド②のオーバライド
        Console.WriteLine("翼と脚で走る");
    }
}
class mini267 {
    public static void Main() {
        FastRunAble Veldra = new Dragon(); //派生インターフェイスを型とする変数
        Veldra.fastrun(); //抽象メソッド②のオーバライドを呼ぶ
        RunAble Veldra2 = Veldra; //基本インターフェイスを型とする変数
        Veldra2.run(); //抽象メソッド①のオーバライドを呼ぶ
    }
}

p.270(インターフェイスの継承と名前の隠ぺい)

・派生インターフェイスで、基本インターフェイスと同じシグニチャの仮想メンバを定義できる
・これは、クラスの継承の場合と同様に「名前の隠ぺい(p.228)」となる
・よって、newキーワードを前置して、名前の隠ぺいであることを明示すると良い

p.270 interface07.cs

//p.270 interface07.cs
using System;
interface IMyInterface { //基本インターフェイス
    void show1(); //抽象メソッド①
    void show2(); //抽象メソッド②
}
interface IMyInterface2 : IMyInterface { //派生インターフェイス
    //ここに「void show1(); //抽象メソッド①」があるとみなされるが隠ぺいされる
    //ここに「void show2(); //抽象メソッド②」があるとみなされる
    new void show1(); //抽象メソッド①に対する名前の隠ぺいになる
    void show3(); //抽象メソッド③
}
class MyClass : IMyInterface2 { //派生インターフェイスを実装するクラス
    public void show1() { //抽象メソッド①に対する名前の隠ぺいのオーバライド
        Console.WriteLine("show1");
    }
    public void show2() { //抽象メソッド②のオーバライド
        Console.WriteLine("show2");
    }
    public void show3() { //抽象メソッド③のオーバライド
        Console.WriteLine("show3");
    }
}
class interface07 {
    public static void Main() {
        MyClass mc = new MyClass();
        mc.show1(); //抽象メソッド①に対する名前の隠ぺいのオーバライドを呼ぶ
        mc.show2(); //抽象メソッド②のオーバライドを呼ぶ
        mc.show3(); //抽象メソッド③のオーバライドを呼ぶ
    }
}

ミニ演習 mini268.cs

・派生インターフェイスで、基本インターフェイスの抽象メソッドと同じシグニチャで戻り値型が異なる抽象メソッドを定義して
 名前の隠ぺいができるが、
 派生インターフェイスを実装するクラスで、戻り値型が異なる抽象メソッドのみをオーバライドすると
 エラーになることを確認しよう
・これを「インターフェイス名.メソッド名」で両方をオーバライドするとエラーが解消することを確認しよう
・基本インターフェイス: interface RunAble { void run(); }
・派生インターフェイス: interface FastRunAble { new int run(); }
・派生インターフェイスを実装するクラス: class Dragon : FastRunAble {…}
※ p.272 interface08.csでは戻り値型も同じ抽象メソッドで名前を隠ぺいしているが、
 実務的な必要性はあまりないので、この例で理解すると良い

作成例

//ミニ演習 mini268.cs
using System;
interface RunAble { //基本インターフェイス
    void run(); //抽象メソッド①
}
interface FastRunAble  : RunAble { //派生インターフェイス
    //ここに「void run();//抽象メソッド①」があるとみなすが隠ぺいされる
    new int run(); //抽象メソッド②
}
class Dragon : FastRunAble { //派生インターフェイスを実装するクラス
    void RunAble.run() { } //抽象メソッド①のオーバライド
    int FastRunAble.run() { //抽象メソッド②のオーバライド
        Console.WriteLine("脚で走る");
        return 100;
    }
}
class mini266 {
    public static void Main() {
        FastRunAble Veldra = new Dragon(); //派生インターフェイスを型とする変数
        int speed = Veldra.run(); //抽象メソッド②のオーバライドを呼ぶ
        Console.WriteLine("{0}km/h", speed);
    }
}

p.254 練習問題1・2 ヒント

・p.231 override01.csを基にすると良い
・Mainメソッドは下記のようにすると良い
 ① 派生クラスであるA2クラスのインスタンスを生成
 ② ①のCalcメソッドを実行し、差が得られることを確認
 ③ ①を基本クラスであるA1を型とする変数に代入
 ④ ③のCalcメソッドを実行し、和が得られるか差が得られるかを確認

作成例:p.254 練習問題1

//p.254 練習問題1
using System;
class A1 { //和を返すメソッドを持つ基本クラス
    public virtual int Calc(int a,int b) { //オーバライド可能な仮想メソッドにする
        return a + b; //和を返す
    }
}
class A2 : A1 { //差を返すメソッドを持つ派生クラス
    public override int Calc(int a,int b) { //オーバライドメソッド
        return a - b; //差を返す
    }
}
class sampleclass {
    public static void Main() {
        A2 a = new A2(); //派生クラスのオブジェクトを生成
        Console.WriteLine("{0}",a.Calc(1,2)); //差を返すメソッドになる
        A1 b; //基本クラスを型とする変数を定義
        b = a; //派生クラスのオブジェクトを代入しても…
        Console.WriteLine("{0}",b.Calc(1,2)); //多態性により、差を返すメソッドになる
    }
}

作成例:p.254 練習問題2

//p.254 練習問題2
using System;
class A1 { //和を返すメソッドを持つ基本クラス
    public int Calc(int a,int b) { //通常のメソッドにする
        return a + b; //和を返す
    }
}
class A2 : A1 { //差を返すメソッドを持つ派生クラス
    new public int Calc(int a,int b) { //名前の隠ぺいとなるメソッド
        return a - b; //差を返す
    }
}
class sampleclass {
    public static void Main() {
        A2 a = new A2(); //派生クラスのオブジェクトを生成
        Console.WriteLine("{0}",a.Calc(1,2)); //差を返すメソッドになる
        A1 b; //基本クラスを型とする変数を定義
        b = a; //派生クラスのオブジェクトを代入すると
        Console.WriteLine("{0}",b.Calc(1,2)); //名前の隠ぺいにより、和を返すメソッドになる
    }
}

p.274 練習問題 ヒント

・文字列の文字数を返すには、Lengthプロパティ(p.73)を用いると良い
手順
① インターフェイス名は特に指定なしなので、仮にCountableとする
② ①の中に、抽象メソッド int Count(string str); を定義する
③ Countableインターフェイスを実装するクラス名も特に指定なしなので、仮にDragonとする
④ ③において、int Count(string str)メソッドをオーバライドする
⑤ ④の中で、引数strで受け取った文字列の文字数をreturnする
⑥ 実行用のクラス名も特に指定なしなので、仮にex10とする
⑦ ⑥において、Mainメソッドを定義する
⑧ ⑦の中で、Dragonクラスのインスタンスを生成する
⑨ ⑧を用いてCountメソッドに適当な文字列を与えた結果をConsole.WriteLineすることで動作確認

作成例

//p.274 練習問題
using System;
interface Countable { //インターフェイスの定義
    int Count(string str); //抽象メソッド
}
class Dragon : Countable { //インターフェイスを実装したクラスの定義
    public int Count(string x) { //抽象メソッドのオーバライド
        return x.Length;
    }
}
class ex10 { //実行用クラス
    public static void Main() {
        Dragon y = new Dragon(); //インターフェイスを実装したクラスのオブジェクト生成
        Console.WriteLine("aの文字数は{0}です", y.Count("Happy!!"));
    }
}

コメントを残す

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