LoginSignup
1
0

More than 3 years have passed since last update.

【PHP】遅延静的束縛 static/self/parent

Last updated at Posted at 2020-08-09

はじめに

PHP資格勉強中の備忘録として記事を書きます。
内容は「PHP5技術者認定上級試験問題集」に出てきたものをまとめています。

static self parentが示すスコープで、どのクラスのメソッドが
呼び出されるのか本当にややこしかったのでまとめます。

まとめ

スコープ
self selfが記載されたクラス
static 非転送コールのクラス
parent parentが記載されたクラスの親クラス
  • 転送コール
    • self、static、parentによる静的メソッドのコール
  • 非転送コール
    • 明示的にクラス名を指定したもの(クラス名::メソッド名)

self

self「selfが記載されたクラス」がスコープとなる。
よって以下の実行結果は「foo」となる。

class Foo {
  public static function who() {
    echo 'foo';
  }

  //selfでwho()の呼び出し
  public static function test() {
    self::who();
  }
}

class Bar extends Foo {
  public static function who() {
    echo 'bar';
  }

//Barクラスでtest()呼びだす
Bar::test();

static

static「非転送コールのクラス」がスコープとなる。
よって以下の実行結果は「bar」となる。
非転送コールである「Bar::test()」まで遡り、Barのメソッドが呼ばれる。

class Foo {
  public static function who() {
    echo 'foo';
  }

  //staticでwho()の呼び出し
  public static function test() {
    static::who();
  }
}

class Bar extends Foo {
  public static function who() {
    echo 'bar';
  }

//Barクラスでtest()呼びだす
Bar::test();

parent

parent「parentが記載されたクラスの親クラス」がスコープとなる。
よって以下の実行結果は「foo」となる。

class Foo {
  public static function who() {
    echo 'foo';
  }
}

class Bar extends Foo {
  public static function who() {
    echo 'bar';
  }

  //parentでwho()の呼び出し
  public static function test() {
    parent::who();
  }

//Barクラスでtest()呼びだす
Bar::test();

ついでに

class ParentClass {
  //クラス名を返す特殊な定数
  public static function get_class_constant() {
    print __CLASS__;
  }

  //関数を呼び出したクラスのクラス名を返す関数
  public static function get_class_function() {
    print get_called_class();
  }

class ChildClass extends ParentClass {}

//子クラスから両方呼ぶ
ChildClass::get_class_constant();
ChildClass::get_class_function();

実行結果

ParentClass
ChildClass

まとめ

class X {
  public static function foo() {
    //staticでwho()を呼ぶ
    //非転送コールを探す
    static::who();
  }

  public static function who() {
    echo __CLASS__;
  }
}

class Y extends X {
  public static function test() {
    //それぞれでfoo()を呼び出す
    X::foo();
    parent::foo();
    self::foo();
  }

  public static function who() {
    echo __CLASS__;
  }
}

class Z extends Y {
  public static function who() {
    echo __CLASS__;
  }
}

//Zでtest()を呼び出す
Z::test();

実行結果

X Z Z

最後に

なんともややこしい。
理解したはずなのに、記事書いてたときにごちゃごちゃしました。笑
間違っていたら教えて下さい。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0