あーる学習帳

自分が勉強したことや気になることなど、99%自分用です。コードを書いてるのでPCから閲覧を推奨。

PHP入門:クラスとインスタンス、継承、アクセス権

今日は早めに始める作戦。

昨日の終了時にVagrantの終了を忘れていたのか、Vagrant Upでエラーを吐くという現象がありました。

VagrantUpで起動失敗→VagrantHaltでいったん終了→VagrantUpをもう一回やったらVagrantは起動したので、終了を忘れるとこういうことになるんだという教訓にします。

 

#18

クラスとインスタンスのお話。

複雑な処理についてはクラス(class)インスタンス(instance)を使うことで実現していく。例えば、「user」というクラスを作る場合は以下のような図になる。

f:id:R_de_aru:20180613201640p:plain

正直今回の説明はわかりづらい…。

classでデータの構造を定義し、instanceを作成してそれをinstanceごとに使っていくという話らしい。instanceを定義するには「$Tom=new User("Tom")」という形で定義し、定義した先では「$Tom->name」や「$Tom->sayHi()」という形でclassのProperty(クラスが持つ変数)Method(クラスが持つ関数)が使えますとのこと。Constructorというものもあるが今回は触れない。

あとはやりながら感覚を掴むしかなさそう…。全部英語で書いたけど、今後は普通にクラスやインスタンスとして表記していきます。最初くらいはちゃんとしたかったので。

この図を作るのには以下のサイトが役に立った。Web上でフローチャートを作るサイト、無料なのでぜひ。

Flowchart Maker & Online Diagram Software

 

#19

今回はクラスを作成する。

今回は下記のようにコードを作成し、userクラスを作る。

class User {

  // この中にプロパティ、コンストラクター、メソッドを定義

  // Property

  public $name;

  // Constractor

  public function __construct($name){

    $this->name = $name;

  }

  // Method

  public function sayHi() {

    echo "Hi,I am $this->name!";

  }

}

クラス名は必ず先頭が大文字になる。

インストラクターがなんとなくわかった気がする。インストラクターの名前は「__constuct」で固定らしい。最初は半角のアンダーバー2つ。constructの後のかっこに入れたクラス内の変数について、インスタンス側でその変数に値を入れるときにどのような形で呼ばれればその変数を使うかということらしい。感覚的だなぁとは思うけど、今はこのようなイメージ…。わかりやすい説明をまた探してみよう。

これでクラスができたので、インスタンスを作成して使ってみよう。

//(上のコードの続き)

$Tom =new User("Tom"); 

$Bob =new User("Bob"); 

$Tom->name;

$Bom->sayHi();

こうすると、画面には「TomHi,I am Bob!」と表示される。

 

#20

クラスの継承について。そういう単語だけは聞いたことがある(意味は知らない)。

これはあるクラスをもとにして新しいクラスを作るときに有効な手法だとのこと。

#19で作ったuserクラスを継承して新しいクラスを作る場合は以下のように書く。

class User{

  // #19と同じ内容

}

class AdminUser extends User{

  public function sayHello(){

    echo "Hello From Admin!";

  }

}

$steve = new AdminUser("Steve");

echo $steve->name;

$steve->sayHi();

$steve->sayHello();

これでAdminUserクラスもUserクラスで定義した$nameやsayHiが使えるようになる。

なお、AdminUserはUserクラスの派生なので子クラス、この場合のUserクラスを親クラスと呼ぶ。AdminUserクラス独自の変数や関数を作ることもできる。

また、子クラスの処理で親クラスのメソッドやプロパティを上書きすることも可能。オーバーライドというらしい。

class User{

  // #19と同じ内容

}

class AdminUser extends User{

  public function sayHello(){

    echo "Hello From Admin!";

  }

  // override

  public function sayHi(){

    echo "[Admin] Hi,I am $this->name!";

  }

}

$tom=new User("Tom");

$steve=new AdminUser("steve");

$tom->sayHi();

$steve->sayHi();

オーバーライドする場合は子クラス側で親と同じメソッド名を定義して別の処理を書けばOK。例ではtomとsteveはそれぞれUserとAdminUserに属するインスタンスだが、同じようにSayHiメソッドを使っても画面に表示される内容が変わることがわかる。

親クラス側で子クラスでのオーバーライドを禁止する方法もある。

class User {

 

  public $name;

  public function __construct($name){

    $this->name = $name;

  }

  final public function sayHi() {

    echo "Hi,I am $this->name!";

  }

}

メソッド名の前にfinalとつければオーバーライドを禁止することになる。 

上のように書き換えて実行しようとすると、ビルトインサーバーでは「cannot override」というエラーを吐く。

 

#21

プロパティやメソッドのアクセス権について。

今まで書いてきたpublicというワードがアクセス権を示すワードのひとつである。

アクセス権を示すワードには以下の種類がある。

  • private:そのクラス内からのみアクセス可能
  • protected:そのクラス内+親子クラスからアクセス可能
  • public:どこからでもアクセス可能

試しに以下のように書き換え。

class User {

  // public $name;

  private $name;

  public function __construct($name){

    $this->name = $name;

  }

  public function sayHi() {

    echo "Hi,I am $this->name!";

  }

}

class AdminUser extends User{

  public function sayHello(){

    echo "Hello From $this->name";

  }

}

$tom=new User("tom");

echo $tom->name;

この状態で最後のecho $tom->name;を実行するとエラーになる。ビルトインサーバー側では「Cannot access private property User::$name」とエラーを吐く。継承したクラスからも使えなくなる。

(上のコードに追加)

$steve=new AdminUser("steve");

$steve->sayHello(); 

こうすると画面には「Hello From 」しか出ない。ビルトインサーバー側ではエラーではないので実行そのものは可能だが、「Undefined property: AdminUser::$name」というメッセージが出る。

「継承したクラスからは使いたいがpublicにはしたくない…」というときにはprotectedを使えばよい。

安全なプログラムを書く際には必要不可欠な知識なので覚えておこう。

 

#22

staticを使おうという話。

インスタンスを作らなくても使えるプロパティやメソッドを定義する。

class User {

  public $name;

  public function __construct($name){

    $this->name = $name;

  }

  public function sayHi() {

    echo "Hi,I am $this->name!";

  }

  public static function getMessage(){

    echo "Hello From User Class!";

  }

}

User::getMessage();

アクセス権を示した後にstaticと書けばOK。 

インスタンスを作らないので、そのクラス独自のプロパティは使えないことに注意。

これにアクセスするには「(クラス名)::(メソッド名)」と書く。コロン2つ。

プロパティのstatic化についても例を作成。

class User {

  public $name;

  public static $count =0; //$countを初期化して0とする

  public function __construct($name){

    $this->name = $name;

    self::$count++; //インスタンス化されるたびにカウントが増える

  }

  public function sayHi() {

    echo "Hi,I am $this->name!";

  }

  public static function getMessage(){

    echo "Hello From User Class!";

  }

}

$tom=new User("tom");

$bob=new User("bob");

echo User::$count;

インスタンスが作成されるたびにカウントしていくプログラムになる。

クラスの中のstaticで定義したプロパティやメソッドを呼び出したい場合はselfというワードを使う。この場合、画面には2回インスタンスを作ったので2と表示される。

 

今夜はここまで。どうもインストラクターの理解がしっくりこない…。