アプリ版:「スタンプのみでお礼する」機能のリリースについて

メンバにアクセスできる件について

PHPでスーパークラスで定義したprivateのメンバにサブクラスからアクセスできる件について
質問です。
class TestClass {
private $value01 = "スーパークラスの private メンバ";

public function testMethod01 () {
print "スーパークラスのパブリックメソッド";
print "<h1>{$this->value01}</h1>";
}
protected function testMethod02(){
print "スーパークラスの protected メソッド";
}
private function testMethod03(){
print "スーパークラスの private メソッド";
}
public function getMethodList(){
print_r(get_class_methods($this));
}
}

class ExClass extends TestClass{

private $value01 = "サブクラスの private メンバ";
}

$obj = new ExClass();

$obj-> testMethod01();

と上記のようにサブクラスのインスタンスから継承したpublicなメソッド testMethod01()を実行すると
スーパークラスのprivateなプロパティにアクセスできてしまいます。
これってどういうことでしょうか?privateメンバってそのクラスの中からだけしかアクセスできませんよね?
上記では、サブクラスからアクセスしているような状態にみえますがどういうことでしょうか?

ご教授御願い致します。

A 回答 (2件)

#1です



 >$obj = new ExClass();
 >$obj-> testMethod01();
 >ここから見える(アクセスできる)かどうかです。
 というのは、スーパ-クラスを継承したExClassというサブクラスから継承元までさかのぼってという意味でしょうか?

そこはひとまず置いて考えてみると分かりやすくなると思います。
サブクラスからアクセスできるのはtestMethod1とtestMethod2です。
ここまではたぶん理解されていると思います。

ではtestMethod1(もしくはtestMethod2)から見える範囲は?
→TestClass内の各メソッドやプロパティです。

単純にこれだけの話です。なので・・・

 以下メソッドは、スーパークラスで定義してサブクラスに継承されたクラスですよね。
 public function testMethod01 () {
 print "スーパークラスのパブリックメソッド";
 print "<h1>{$this->value01}</h1>";
 }

 >$obj-> testMethod01();
 上の継承したメソッドtestMethod01()を実行している時点でExClassのインスタンスだけど
 実際はスーパ-クラス内に入りこんでTestClass(スーパクラス)として振る舞っているということでしょうか?

「入り込んで」の解釈の仕方が適切なのかはわかりませんが、そういう理解の仕方でもよいと思います。
(ちょっと適当)


 また、このtestMethod01というメソッドと全く同じ内容でサブクラスでオーバーライドした場合は上記とは異なる動きになりますよね?
 オーバ-ロードした場合、サブクラス内で【$this->value01】というプロパティを探す動きにかわるとおもいますが、
 オーバ-ロードした場合は完全に、サブクラスとして振る舞うというような解釈でしょうか?

これはサブクラス内にtestMethod01を定義(オーバーライド)しているという意味ですかね?
こんな意味で間違ってなければ・・・
class ExClass extends TestClass{

  private $value01 = "サブクラスの private メンバ";
  
  public function testMethod01 () {
   print "ここに表示されるのは?";
   print "<h1>{$this->value01}</h1>";
  }
}

ここでの$this->vakue01はサブクラスの値です。
なぜなら$thisはサブクラスなので。

ってここまで書いて気づきましたがオーバーロードですか?オーバーライドですか?
PHPでオーバーロードって最近はあまり聞きませんが、意味合いが異なってきますのでちょっと悩ましいです。
これはJavaチックな考え方ですかね?あんま詳しくないのでよくわかりませんが・・・
http://php.net/manual/ja/language.oop5.overloadi …
    • good
    • 0
この回答へのお礼

ありがとうございます。
なんとかつかめた気がします。
オーバーロードに関しては入力間違いです。ごめんなさい。

class SuperClass{
public $publicValue = "スーパークラスのパブリックプロパティ";
protected $protectedValue = "スーパークラスのプロテクティッドプロパティ";
private $privateValue = "スーパークラスのプライベートプロパティ";
public function superPublicMethod(){
print "どこからでも見えるメソッド";
}
protected function superProtectedMethod(){
print "親及び子クラスのクラス定義の中のみ参照可";
}
private function superPrivateMethod(){
}
public function superGetMethodList(){
var_dump(get_class_methods($this));
var_dump(get_class_vars(get_class($this)));
}
}


class SubClass extends SuperClass{
public $publicValue = "サブクラスのパブリックプロパティ";
protected $protectedValue = "サブクラスのプロテクティッドプロパティ";
private $privateValue = "サブクラスのプライベートプロパティ";
public function subGetMethodList(){
var_dump(get_class_methods($this));
var_dump(get_class_vars(get_class($this)));
}
}

$obj = new SubClass();

//クラス定義の外側なので private protected メソッドは不可視である。
var_dump(get_class_methods($obj));
var_dump(get_class_vars(get_class($obj)));


$obj -> subGetMethodList();

$obj -> superGetMethodList();

------------------------------------------------------------------------------------------------
array
0 => string 'subGetMethodList' (length=16)
1 => string 'superPublicMethod' (length=17)
2 => string 'superGetMethodList' (length=18)

array
'publicValue' => string 'サブクラスのパブリックプロパティ' (length=48)
------------------------------------------------------------------------------------------------
array
0 => string 'subGetMethodList' (length=16)
1 => string 'superPublicMethod' (length=17)
2 => string 'superProtectedMethod' (length=20)
3 => string 'superGetMethodList' (length=18)

array
'publicValue' => string 'サブクラスのパブリックプロパティ' (length=48)
'protectedValue' => string 'サブクラスのプロテクティッドプロパティ' (length=57)
'privateValue' => string 'スーパークラスのプライベートプロパティ' (length=57)
------------------------------------------------------------------------------------------------
array
0 => string 'subGetMethodList' (length=16)
1 => string 'superPublicMethod' (length=17)
2 => string 'superProtectedMethod' (length=20)
3 => string 'superPrivateMethod' (length=18)
4 => string 'superGetMethodList' (length=18)

array
'publicValue' => string 'サブクラスのパブリックプロパティ' (length=48)
'protectedValue' => string 'サブクラスのプロテクティッドプロパティ' (length=57)
'privateValue' => string 'スーパークラスのプライベートプロパティ' (length=57)
------------------------------------------------------------------------------------------------
と上記のようなコードを描いてしらべたところなんとか把握できました。
どうやらあちこちのサイトで描かれているサブクラスはスーパークラスのpublicおよびprotectedのメンバが継承されるという
記述を数多くみてきたせいで、サブクラスにはスーパークラスのprivateはいっさい継承されないものとおもっていました。
だから、サブクラスからスーパークラスのprivateなメンバにアクセスできるのが謎だったんですね。これはマニュアルもちょっと記述の仕方を考えてほしいなとおもったところです。

お礼日時:2012/06/29 01:26

えーとそういう事です・・・



あくまで$obj->testMethod01() はpublicメソッドへのアクセスなので問題はないです。

クラスの外側
$obj = new ExClass();
$obj-> testMethod01();
ここから見える(アクセスできる)かどうかです。

testMethod01からは「同じクラス内」のメンバ変数にアクセスできるので、そのような状態になります。


testMethod01がgetterだと思えば分かりやすいかと。
(より混乱されるようでしたらこれは忘れてください)

この回答への補足

え-と
>$obj = new ExClass();
>$obj-> testMethod01();
>ここから見える(アクセスできる)かどうかです。
というのは、スーパ-クラスを継承したExClassというサブクラスから継承元までさかのぼってという意味でしょうか?

以下メソッドは、スーパークラスで定義してサブクラスに継承されたクラスですよね。
クラス定義自体は省略します。

public function testMethod01 () {
print "スーパークラスのパブリックメソッド";
print "<h1>{$this->value01}</h1>";
}

>$obj-> testMethod01();
上の継承したメソッドtestMethod01()を実行している時点でExClassのインスタンスだけど
実際はスーパ-クラス内に入りこんでTestClass(スーパクラス)として振る舞っているということでしょうか?


また、このtestMethod01というメソッドと全く同じ内容でサブクラスでオーバーライドした場合は上記とは異なる動きになりますよね?
オーバ-ロードした場合、サブクラス内で【$this->value01】というプロパティを探す動きにかわるとおもいますが、
オーバ-ロードした場合は完全に、サブクラスとして振る舞うというような解釈でしょうか?

補足日時:2012/06/27 23:27
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!