そういえば今まであんまり使わなかったけど、遅延静的束縛というものを使ってみる。
class Animal{
public function cry(){
print(self::_getVoice());
}
protected static function _getVoice(){
return '(「・ω・)「がおー';
}
}
class Dog extends Animal{
protected static function _getVoice(){
return 'bow!';
}
}
$pochi = new Dog();
$pochi->cry();// (「・ω・)「がおー
マニュアルを参照すると以下のような記述がされている。
静的遅延束縛は直近の “非転送コール”(self:: や parent::、static:: による静的なコール、 あるいはクラス階層の中での forward_static_call() によるコール) のクラス名を保存します。 静的メソッドの場合、これは明示的に指定されたクラス (通常は :: 演算子の左側に書かれたもの) となります。静的メソッド以外の場合は、そのオブジェクトのクラスとなります。 get_called_class() 関数を使うとコール元のクラス名を文字列で取得できます。 static:: はこのクラスのスコープとなります。
selfでは直近のクラスが参照されるので、上述の例の場合はselfはAnimalクラスということになる。pochiにもっと犬らしくして欲しい時は以下のようにstaticを用いて記述する。
<?php
class Animal{
public function cry(){
print(static::_getVoice());
}
protected static function _getVoice(){
return '(「・ω・)「がおー';
}
}
class Dog extends Animal{
protected static function _getVoice(){
return 'bow!';
}
}
$pochi = new Dog();
$pochi->cry();// bow!
親クラスから子クラスのメソッドが呼び出される感じなのでアクセス権はprotected以上でないと「Fatal error: Call to private method」となる。
Pythonでは以下のように問題なく、selfを使用することができる。
class Animal:
def cry(self):
print(self._getVoice())
def _getVoice(self):
return 'gao!'
class Dog(Animal):
def _getVoice(self):
return 'bow!'
pochi = Dog()
pochi.cry()# bow!
Javaの場合はそもそもselfがない。クラス名を直接指定する必要があり、明示しない時はカレントクラスのメソッドがコールされる。
static class Animal{
public static String cry(){
return getVoice();// 明示しない場合はAnimal.となる
}
protected static String getVoice(){
return "(「・ω・)「がおー";
}
}
static class Dog extends Animal{
protected static String getVoice(){
return "bow!";
}
}
Dog pochi = new Dog();
Log.e("cry", pochi.cry());// (「・ω・)「がおー