今回は、既に定義したクラスをもとに、新しいクラスを定義することが
できます。新しいクラスを作成することを、
クラスを拡張する(extends)
といい、たとえば、名前や年齢を表すクラスをもとにして、
住所や電話番号も管理するクラスを作成することができます。
新しいクラスは、既存クラスのメンバ・メソッドを
「引き継ぐ」仕組みです。既存クラスのメンバ・メソッドを書かなくて
大丈夫です。既存クラスのメンバ・メソッドに追加する形で書きます。
新しく拡張したクラスが既存クラスしを受け継ぐことを
継承(inheritance)といいます。
このとき、もととなる既存クラスのことを基本クラス(base class)といい
新しいクラスを派生クラス(derived class)といいます。
クラスを拡張する
派生クラスは、extendsを使って以下のように書きます。
class 派生クラス extends 基本クラス名
{
派生クラスに追加するメンバ変数 = 値;
・・・・
function 派生に追加するメソッド(引数リスト){
・・・・
}
}
例えば、お客を表すCustomerクラスをもとにして、ネットユーザーを
表すUserクラスを作成します。Customerクラスは名前と年齢を管理します。
これにUserクラスは電話番号、住所を管理します。
class User extends Customer
{
private $adr = ""abc@co.jp";
private $tel = "00-0000-0000";
function __construct($na,$ag,$ad,$te)
{
parent::__construct($na,$ag);
$this->adr = $ad;
$this->tel = $te;
}
function getName(){ return "会員:" . $this->name; }
function getAdr(){ return $this->adr; }
function getTel(){ return $this->tel; }
}
CustomerクラスからUserクラスを拡張すると、Userクラスは、
Customerクラスのメンバ変数、メソッドを引き継ぐことができます。
Userクラスは引き継いだものに関して、特にコードに書く必要はなく、
派生クラス独自のメンバ変数・メソッドを書けば大丈夫です。
派生クラスでコンストラクタを定義した場合、
基本クラスのメンバを初期化するには、基本クラスのコンストラクタを
記述して呼び出す必要があります。そのとき
「parent::コンストラクタ名」と指定します。
「parent::」は基本クラスを意味しています。
・基本クラスから派生クラスを拡張できる。
・基本クラスは派生クラスのメンバを継承する。
オーバーライドのしくみ
基本クラスと派生クラスには、同じ名前のメソッドを持たせることが
できます。Customerクラスには名前を管理するgetName()メソッドが
あります。このとき、Userクラスでも、ユーザーの名前を管理する
getName()メソッドを定義することができます。
class Customer
{
・・・
function getName(){ return $this->name; }
・・・
}
class User
{
・・・
function getName(){ return $this->name; }
・・・
}
上記の場合、派生クラスではどちらのメソッドが呼ばれるのか。
下記のコードを書いてみると。
$cu = new Customer;
echo $cu->getName(); //基本クラスのメソッドが実行される
$ur = new User;
echo $ur->getName(); //派生クラスのメソッドが実行される
基本クラスのオブジェクトを表す変数から、getName()メソッドを
呼び出すと、基本クラスのgetName()メソッドが呼ばれます。
派生クラスのオブジェクトを表す変数から、getName()メソッドが、
呼びだすと、派生クラスのgetName()メソッドが呼ばれます。
派生クラスのメソッドが、基本クラスのメソッドに代わり機能することを
オーバーライド(override)と呼んでいます。
同じ名前のメソッドがオブジェクトのクラスに応じて機能するので、
分かりやすいコードを書くことができます。
派生クラスのメソッドが、基本クラスの同じ名前のメソッドに
変わって機能することをオーバーライドといいます。
サンプルコードの実行結果はこちら
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 |
<!doctype html> <html> <head> <meta charset="utf-8"> <title></title> <link rel="stylesheet" href="../style.css"> </head> <body> <?php $user[0] = new User("山田",30,"abc@abcdef.co.jp","12-3456-7890"); echo $user[0]->getName(); echo "<br>"; echo $user[0]->getAge(); echo "<br>"; echo $user[0]->getAdr(); echo "<br>"; echo $user[0]->getTel(); echo "<br>"; //基本クラスの定義 class Customer { protected $name =""; protected $age =18; function __construct($na,$ag){ $this->name = $na; if( $ag >= 18 && $ag <= 65 ){ $this->age = $ag; }else{ $this->age = -1; } } function getName(){ return $this->name; } function getAge(){ return $this->age; } } //派生クラスの定義 class User extends Customer { private $adr = ""; private $tel =""; function __construct($na,$ag,$ad,$te){ parent::__construct($na,$ag); $this->adr = $ad; $this->tel = $te; } function getName(){return "名前:" . $this->name;} function getAdr(){ return $this->adr;} function getTel(){ return $this->tel;} } ?> </body> </html> |
上記のサンプルコード、Customerクラスのメンバ変数にはprotectedと言葉が
ついています。protectedはアクセス指定子のひとつで、
クラスの外部からは利用できませんが、そのクラスを継承したクラスでは
利用できるようにするものです。今回は、派生クラスから
メンバ変数にアクセスできるようにする為、protectedを使っています。
final
派生クラスでオーバーライドさせたくないとき、
基本クラスでメソッドを定義する際に、finalをつけることができます。