継承の仕組みを知る
クラスを拡張する(extends)
新しいクラスは、既存のクラスのメンバー変数・メソッドを「受け継ぐ」しくみになっています。既存のクラスのメンバー変数・メソッドを記述する必要がありません。既存のクラスに新しく必要となるメンバー変数・メソッドを付け足すようにコードを書いていくことができるのです。
新しく拡張したクラスが既存のクラスの資産(メンバー)を受け継ぐことを継承(inheritance)といいます。
このとき、もとになる既存のクラスを基本クラス(base class)と呼びます。新しいクラスを派生クラス(derived class)と呼びます。
クラスを拡張する
構文:クラスの拡張
class 派生クラス名 : 基本クラス名
{
新しいフィールド;
新しいメソッド(引数リスト)
{
…
}
}
次のように派生クラスでColorPictureを定義できるのです。
class ColorPicture : Picture
{
...
...void Move() //基本クラスと同じ名前とすることもできます
{
}
}
基本クラスを拡張して、派生クラスを定義することができる。派生クラスは、基本クラスのメンバーを継承する。
派生関係のあるクラスはまとめて扱える
派生クラスのオブジェクトは基本クラスのオブジェクトとしても扱える。
Picture p = new ColorPicture();
Picture[] p = new Picture[2]; //基本クラスの配列
p[0] = new Picture();
p[1] = new ColorPicture();
for (int i=0; i<p.Length; i++)
{
p[i].Move(); //派生クラスのオブジェクトをまとめて扱うことができる
}
派生クラスから基本クラスにアクセス する
基本クラスのprivateメンバーには派生クラスからもアクセスすることはできないということです。しかし、派生クラスと基本クラスには密接に関係するため、これでは不便なこともあります。
基本クラスのメンバーに、protectedというアクセス修飾子をつけておくということを行います。protectedを指定することで、派生クラスのみからアクセスでき、そのほかのクラスからアクセスできないようにすることができます。
class Picture
{
protected int top;
protected int left;
...
}
class ColorPicture
{
...
public void Move()
{
top = top +100;
left = left +100;
}
}
protectedメンバー派生クラスから、基本クラスのprotectedメンバにアクセスすることができます。
オーバーライドが行われるようにする
基本クラスにおいて、同じ名前で再定義される予定のあるメンバにはvirtualというキーワードをつけておきます。そして派生クラスでは同じ名前で処理を上書きしたいメンバーにoverrideというキーワードをつけます。
class Picture
{
virtual void Move()
{
...
}
}
class ColorPicture : Picture
{
override void Move()
{
...
}
}
新しい派生クラスのメンバーによって、元の暮らすのメンバーを上書きすることができるわけです。このしくみをオーバーライド(override)といいます。
using System.Windows.Forms;
using System.Drawing;
namespace lesson5
{
class Sample3
{
static void Main(string[] args)
{
Form fm = new Form();
fm.Text = "ようこそC#へ";
PictureBox[] pb = new PictureBox[2];
for (int i = 0; i < pb.Length; i++)
{
pb[i] = new PictureBox();
pb[i].Parent = fm;
}
Picture[] p = new Picture[2];
p[0] = new Picture();
p[1] = new ColorPicture();
for (int i = 0; i < p.Length; i++)
{
p[i].Move();
pb[i].Image = p[i].GetImage();
pb[i].Top = p[i].Top;
pb[i].Left = p[i].Left;
}
Application.Run(fm);
}
}
class Picture
{
private Image img;
protected int top;
protected int left;
public static int count = 0;
public Picture()
{
img = Image.FromFile("E:\\099_Technology\\C#\\csharp\\csharp_train\\lesson2\\google.JPG");
top = 0;
left = 0;
count++; //コンストラクタが呼び出されたときに静的なフィールドであるCountの値を1増やします
}
public static string CountPicture()
{
return "Pictureは" + count + "枚あります。";
}
virtual public void Move()
{
top = top + 10;
left = left + 10;
}
public void SetImage(Image i)
{
img = i;
}
public Image GetImage()
{
return img;
}
public int Top
{
set { top = value; } //プロパティとして値を設定する
get { return top; } //プロパティとして値を取得する
}
public int Left
{
set { left = value; } //プロパティとして値を設定する
get { return left; } //プロパティとして値を取得する
}
}
class ColorPicture : Picture
{
override public void Move()
{
top = top + 100; //protectedメンバーにアクセスできます
left = left + 100; //protectedメンバーにアクセスできます
}
}
}
実行画面
ここでは同じ名前のMove()メソッドが、それぞれ実際のオブジェクトのクラスに応じて機能しているわけです。
このように同じ名前が実際のオブジェクトのクラスに応じて機能するしくみは、多態性(polymorphism)と呼ばれています。
抽象クラスとインターフェイス
なお、基本クラスでは、virtualをつけて複数の派生クラスに対して名前を提供し、派生クラスのオブジェクトをまとめて扱うことだけ目的として設計されるものもあります。このような基本クラスでは、オブジェクトを作成することは必ずしも必要ではありません。
そこで、オブジェクトを作成することができないようにしたクラスを抽象クラス(abstract class)といいます。また、さらに、メソッドの内容を定義できないようにしたものをインターフェイス(interface)といいます。クラスを設計する際にはこうしたしくみも利用して設計を行っていくことになります。おぼえておくとよいでしょう。
構文:抽象クラス
abstract class クラス名 //抽象クラスはオブジェクトを作成することができません
{
virtual メソッド名(引数リスト)
{
}
….
}
構文:インターフェイス
interface インターフェイス名
{
virtual メソッド名(引数リスト); //インターフェイスはメソッドの内容を定義することができません
…
}
コメント