2016-04-26 4 views
2

混乱したタイトルのため申し訳ありません、私はより良いものを見つけることができませんでした。私はPHP/5.6.14によ は、私はこのコードを持っている:最後getFoo()を実行奇妙なPHPの動作、ベースクラスと派生クラスの同じフィールド名、クローンインスタンス

class Base 
{ 
    private $foo; <--- NOTE 
    public function __construct() 
    { 
     $this->foo = "base foo"; 
    } 
    public final function getFoo() 
    { 
     return $this->foo; 
    } 
} 

class Derived extends Base 
{ 
    public $foo; <--- NOTE 
    public function __construct($type) 
    { 
     parent::__construct(); 
     $this->foo = "derived foo"; 
     $this->somethingUndefined = "dynamically declared"; <--- NOTE 
    } 
} 

$base = new Base(); 
var_dump($base->getFoo()); 
$derived = new Derived(0); 
var_dump($derived->getFoo()); 
$clonedDerived = clone $derived; <--- NOTE 
var_dump($clonedDerived->getFoo()); 

は私に与える:

PHPのお知らせ:未定義のプロパティ:派生:: Cで$ fooは: .. \ test.php on line * getFoo()がベースクラスで実装されている行*。

  1. 同じプライベート/パブリックフィールド名
  2. に取り組んで派生クラス
  3. 内の1つまたは複数の動的に宣言したフィールドを持つ:私は一緒にこの三つの条件を置く場合

は、私は予告を取得します派生クラスのインスタンスのクローン

これらのうちの1つ以上を削除すると、通知が消えます。

ここでは何が起こっていますか? $fooは静的ではありません、それは未定義ではありません... 私は例外にすべてのE_ALLをオンにするカスタムばerror_handlerを使用していますし、本当にこれを無視することはできません...

EDIT: これがちょうどです私は問題を再現するために書いた例、実際のコードは大きく異なります。私はプライベート$ fooか何かを公開しようとしていません。フィールドと同じ名前を選んだ別の開発者によってBaseとDerivedが実装され、これを(他の2つの条件と一緒に)実行すると、通知が発生したばかりです。私はAFAIK以来、それが完璧でなければならない理由を理解しようとしています。

答えて

1

PHP7でこの例を実行してもこの通知が出されないため、これはPHPのバグと考えています。さらに、あなたvar_dump($this)定義getFoo()で、それは"foo":"Base":privateが定義されていることをはっきりと見ることができる、そしてオブジェクトDerivedfooは両方のPHP> = 7とPHP < 7で見てください、同様に定義されている場合:しかし、https://3v4l.org/Ob9m7

、私は、あなたがこのコードを使って何をしようとしていても、間違った方向に向かっていると信じています。すでに述べたとおり、ArtisticPhoenixとして。あなたがしていることを再考し、再設計することを強くお勧めします。プライベートメンバーをオーバーライドすることは、OOPごとに可能ではありません。

1

これは予想される動作です。プライベートは、このクラスのみを意味します。そのため、プライベートプロパティ$fooは子クラスには表示されません。それを公開に変更することはできません。あなたが見ていないことに関連する警告が表示される可能性があります。あなたにどのレベルのエラー報告がありますか?

子クラスは、少なくとも親の可視性を維持する必要があります。

で最高のあなたは子クラスでプライベートそれを行うことができ、それはあなたが同じ$foo

お知らせかへのアクセスを提供するつもりはない強制しようとすると、コードの可読性が悪く、プライベート変数を別のものにする。あなたはどんなfooを期待していますか?デフォルトで親に$fooが必要な場合は、子クラスの別の名前を付けてください。子のgetメソッドでif/thenを実行してください。

親クラスでプライベートになっている場合は、基本的に子クラスの$fooの値を変更しようとしています。そしてそれを親から取り出す。私が言及したように、$fooはあなたが期待しているコードを混乱させます。

+0

'Base :: $ foo'は派生クラスからアクセスできないため、同じ名前の新しいプロパティを安全に宣言することができるので、警告/通知/エラーは発生しません。 – slax0r

+0

私はそれをテストしなければならなかった、私は抽象クラスとインターフェイスのラインをもっと考えていた。 – ArtisticPhoenix

+0

'Base :: $ foo'は見えませんが、このクラスはgetFoo()が基本クラスに実装されている行を持っています* .'本当に混乱します。 – ArtisticPhoenix

関連する問題