・p.255「インターフェイスとは」から
提出フォロー:アレンジ演習:p.250 partial01.cs
・MyClassクラスの定義②を、別ファイル(partial02.cs)としてソース分割しよう
作成例:partial01.cs(分割元)
//アレンジ演習:p.250 partial01.cs
using System;
partial class MyClass { //MyClassクラスの定義①
public int x;
}
class partial01 { //partial01クラスの定義
public static void Main() {
MyClass mc = new MyClass();
mc.x = 10;
mc.Show();
}
}
作成例:partial02.cs(分割先)
using System; //自動作成される
partial class MyClass { //MyClassクラスの定義②
public void Show() {
Console.WriteLine("x = {0}", x);
}
}
第10章 インターフェイス
p.255 インターフェイスとは
・インターフェイスの元の意味は「異なる要素を関連付ける仕組み」「接合面」 ・C#では「継承関係のないクラスを関連付けられる仕組み」 ・例えば、画面上にドラゴンと戦闘機が飛び交うゲームにおいて、ドラゴンクラスと戦闘機クラスが継承関係になることは考えづらい。 しかし、双方のクラスが「飛行体」インターフェイスを持てば(実装すれば)、飛行体に含まれるものとしてまとめて扱える ・このように、クラスに基本クラスを定義する形に似た書式で、クラスにインターフェイスを実装できる
p.255 インターフェイスの宣言
・インターフェイスは抽象クラスに似た形で定義し、クラスを徹底的に抽象化したものになる
・具体的には、抽象メソッド、抽象プロパティ、抽象インデクサのみを持つことができるのがインターフェイス
・抽象クラスとは異なり、1つのクラスで複数のインターフェイスを実装できる(クラスの継承は1つのみ)
・これは例えば「飛行体でもあり、走行体でもあるマシン」の場合
・インターフェイスの定義書式: interface インターフェイス名 {…}
・抽象メソッドの定義書式: 戻り値型 メソッド名(引数リスト);
・抽象プロパティの定義書式: 戻り値型 プロパティ名 { get; set; } ※getとsetのどちらかは省略可
・抽象インデクサの定義書式: 戻り値型 this(インデックス型 インデックス);
・インターフェイスの定義例: interface Flyable { string HowToFly(); } //飛行体を示すインターフェイス
p.256 インターフェイスの実装
・クラスの継承と同じ書式で、インターフェイスの実装が可能
・例: class Dragon : Flyable {…}
・クラスの継承とは異なり、複数のインターフェイスの実装が可能
・例: class Dragon : Flyable, Swimable {…}
・抽象クラスの継承と同様に、インターフェイスを実装したクラスでは抽象メンバのオーバライドによる具象(具体化)が求められる
・この時、overrideキーワードは不要だが、publicメソッドにすること
・例: class Dragon : Flyable { public string HowToFly() { return "翼で飛ぶ"; } }
・クラスを利用する側から見ると、インターフェイスを実装しているクラスではインターフェイスがそのクラスの性質を表すことになり、
メリットが大きい
p.257 interface01.cs
//p.257 interface01.cs
using System;
interface IMyInterface { //インターフェイスの定義
void show(string str); //抽象メソッド
int xprop { get; set; } //抽象プロパティ
int this[int i] { get; set; } //抽象インデクサ
}
class MyClass : IMyInterface { //インターフェイスを実装するクラス
int i; //非公開のデータメンバ ※「protected」は不要
int[] arr = new int[10]; //非公開の配列
public void show(string str) { //抽象メソッドのオーバライド(具象化)
Console.WriteLine(str);
}
public int xprop { //抽象プロパティのオーバライド(具象化)
get { return i; } set { i = value; }
}
public int this[int index] { //抽象インデクサのオーバライド(具象化)
get { return arr[index]; } set { arr[index] = value; }
}
}
class interface01 {
public static void Main() {
MyClass mc = new MyClass(); //インターフェイスを実装したクラス
mc.show("Test Interface"); //抽象メソッドのオーバライド(set)を呼ぶ
mc.xprop = 100; //抽象プロパティのオーバライド(set)を呼ぶ
Console.WriteLine("mc.xprop = {0}", mc.xprop); //抽象メソッドのオーバライド(get)を呼ぶ
for (int i = 0; i < 10; i++) {
mc[i] = i * 2; //抽象インデクサのオーバライド(set)を呼ぶ
}
for (int i = 0; i < 10; i++) {
Console.WriteLine("mc[{0}] = {1}", i, mc[i]); //抽象インデクサのオーバライド(get)を呼ぶ
}
}
}
p.259 1つのインターフェイスを複数のクラスで実装する
・継承関係のない複数のクラスを、同じインターフェイスを実装するクラスとして、関連付けることができる ・同じインターフェイスを実装しているクラスであれば、同じ抽象メンバのオーバライドがあることが保証されることがポイント
p.259 interface02.cs
//p.259 interface02.cs
using System;
interface IMyInterface { //インターフェイスの定義
void show(string str); //抽象メソッド
}
class MyClass : IMyInterface { //インターフェイスを実装するクラス①
public void show(string s) { //抽象メソッドのオーバライド①
Console.WriteLine(s);
}
}
class YourClass : IMyInterface { //インターフェイスを実装するクラス②
public void show(string x) { //抽象メソッドのオーバライド②
Console.WriteLine("{0}が入力されました", x);
}
}
class interface02 {
public static void Main() {
MyClass mc = new MyClass();
YourClass yc = new YourClass();
mc.show("abc"); //抽象メソッドのオーバライド①を呼ぶ
yc.show("abc"); //抽象メソッドのオーバライド②を呼ぶ
}
}
p.260(インターフェイスを型とする参照変数)
・抽象クラスのインスタンスは生成できないのと同様に、インターフェイスのインスタンスは生成できない
・抽象クラスを型とする参照変数が定義できるのとと同様に、インターフェイスを型とする参照変数を定義できる
・抽象クラスAを継承する派生クラスBのインスタンスは、Aを型として扱うことができる
・同様に、インターフェイスCを実装するクラスDのインスタンスは、Cを型として扱うことができる
・例: 飛べるものであるドラゴンの「ヴェルドラ」は、飛べるものの「ヴェルドラ」である
inteface Flyable {}
class Dragon : Flyable {}
class Test { void Play() { Dragon Veldra = new Dragon(); Flyable flyone = Veldra; }
・なお、インターフェイスを型とする配列も定義でき、要素として、インターフェイスを実装するクラスのインスタンスを格納できる
・例: 飛べるものであるドラゴンの「ヴェルドラ」は、飛べるもの配列の[0]である
p.261 interface03.cs
//p.261 interface03.cs
using System;
interface IMyInterface { //インターフェイスの定義
int calc(int x, int y); //抽象メソッド
}
class Plus : IMyInterface { //インターフェイスを実装するクラス①
public int calc(int a, int b) { //抽象メソッドのオーバライド①「計算せよ」は加算とする
return a + b;
}
}
class Minus : IMyInterface { //インターフェイスを実装するクラス②
public int calc(int a, int b) { //抽象メソッドのオーバライド②「計算せよ」は減算とする
return a - b;
}
}
class interface03 {
public static void Main() {
IMyInterface im; //インターフェイスを型とする参照変数
Plus p = new Plus();
Minus m = new Minus();
im = p; //Plusクラスはインターフェイスを実装しているのでインターフェイスを型とする参照変数に代入可
Console.WriteLine("im.calc = {0}", im.calc(3, 5)); //抽象メソッドのオーバライドがあると保証される
im = m; //Minusクラスはインターフェイスを実装しているのでインターフェイスを型とする参照変数に代入可
Console.WriteLine("im.calc = {0}", im.calc(3, 5)); //抽象メソッドのオーバライドがあると保証される
}
}
アレンジ演習:p.261 interface03.cs
・インターフェイスの定義を下記に変更
interface Flyable { string HowToFly(); } //飛行体を示すインターフェイス
・実装するクラスを下記に変更
class Dragon : Flyable { public string HowToFly() { return "腕力で飛ぶ"; } }
class F16 : Flyable { public string HowToFly() { return "ジェットで飛ぶ"; } }
・多態性が発揮されることを確認しよう
作成例
//アレンジ演習:p.261 interface03.cs
using System;
interface Flyable { string HowToFly(); } //飛行体を示すインターフェイス
class Dragon : Flyable { //インターフェイスを実装するクラス①
public string HowToFly() { return "腕力で飛ぶ"; } //抽象メソッドのオーバライド①
}
class F16 : Flyable { //インターフェイスを実装するクラス②
public string HowToFly() { return "ジェットで飛ぶ"; } //抽象メソッドのオーバライド②
}
class interface03 {
public static void Main() {
Flyable flyer; //インターフェイスを型とする参照変数
Dragon Veldra = new Dragon();
F16 Blue = new F16();
flyer = Veldra; //Dragonクラスはインターフェイスを実装しているのでインターフェイスを型とする参照変数に代入可
Console.WriteLine("flyer.HowToFly = {0}", flyer.HowToFly()); //抽象メソッドのオーバライドがあると保証される
flyer = Blue; //F16クラスはインターフェイスを実装しているのでインターフェイスを型とする参照変数に代入可
Console.WriteLine("flyer.HowToFly = {0}", flyer.HowToFly()); //抽象メソッドのオーバライドがあると保証される
}
}
アレンジ演習:p.261 interface03.cs つづき
・Flyableインターフェイス型の配列に格納するようにしよう
作成例
//アレンジ演習:p.261 interface03.cs
using System;
interface Flyable { string HowToFly(); } //飛行体を示すインターフェイス
class Dragon : Flyable { //インターフェイスを実装するクラス①
public string HowToFly() { return "腕力で飛ぶ"; } //抽象メソッドのオーバライド①
}
class F16 : Flyable { //インターフェイスを実装するクラス②
public string HowToFly() { return "ジェットで飛ぶ"; } //抽象メソッドのオーバライド②
}
class interface03 {
public static void Main() {
Dragon Veldra = new Dragon();
F16 Blue = new F16();
Flyable[] flyers = { Veldra, Blue }; //上記をインターフェイスを型とする配列に格納
foreach (var w in flyers) { //配列の全要素について繰返す
Console.WriteLine(w.HowToFly()); //抽象メソッドのオーバライドがあると保証される
}
}
}