1

プライベートコンストラクターを使って以下を実装したいと思います。

問題はそれget_class()が戻ることParentBaseです; それでも; get_called_class()を返しますChildClass

基本クラスコンテキストではなく、呼び出し元のクラスコンテキストから__construct()を呼び出すにはどうすればよいですか?

子クラスがたくさんあるので、共有ファクトリメソッドを1つだけにし、子を拡張できないようにします(つまり、newキーワードで作成できないようにします)。

ChildClass::createObject()プライベートChildClassコンストラクターとパブリックParentBaseファクトリメソッドを使用して動作させる方法があるはずです。

<?php
class ParentBase 
{
    public static function createObject() 
    {
        echo get_class() . "<br/>";        // prints ParentBase
        echo get_called_class() . "<br/>"; // prints ChildClass
        return new static();
    }
}

class ChildClass extends ParentBase
{
    private $greeting = "bye";

    private function __construct()
    {
        $this->greeting = "hi";
    }

    public function greet()
    {
        echo $this->greeting;
    }
}

$child = ChildClass::createObject();
$child->greet();

上記からの出力は次のとおりです。

ParentBase
ChildClass
Fatal error: Call to private ChildClass::__construct() from context 'ParentBase' 

保護されたコンストラクターは機能します: http://codepad.viper-7.com/sCgJwA

プライベートコンストラクターはしません: http ://codepad.viper-7.com/YBs7Iz

4

3 に答える 3

1

createObject();これは、の関数であると予想される動作です。したがって、からParentBase戻りますが、から呼び出されたため、から戻ります。ParentBaseget_class()ChildClassChildClassget_called_class()

また、コンストラクターについては、コンストラクターがプライベートとして割り当てられているため、クラス内からのみオブジェクトの作成を制限します。保護することで、親クラスは次のオブジェクトを作成できます。ChildClass

考えられる解決策は、createObject()クラスChildClass自体をオーバーライドすることです。

class ChildClass extends ParentBase
{
    public static function createObject() 
    {
        echo get_class() . "<br/>";
        echo get_called_class() . "<br/>";
        return new static();
    }
}

または、コンストラクターを保護してから、コンストラクターを親クラスにアクセス可能にし、子クラスのサブクラスを制限してfinalにし、親クラスからのみアクセスできるようにします。

于 2012-08-21T02:40:28.993 に答える
0

子コンストラクターは、私の知る限り保護されているか、公開されている必要があります。私は別の問題で同様の問題に遭遇しました。私は私有財産にアクセスしようとしていました。

しかし、何らかの理由で、「ベースファクトリメソッドからプライベート子コンストラクターを呼び出すことはできますか?」という質問があります。あなたのコードを反映していないので、私はこれに答える方法について自分自身を悩ませているので、それを編集することをお勧めします。

于 2012-08-21T02:30:28.837 に答える
0

これがPHP5.4の場合......

他のことをいじってPHPOOPを読んだ後。トレイトがこれを行うことができるようです。

use Traitこの場合、ファクトリを使用してクラスをインスタンス化する必要があることを明確にする表記法が気に入っています。

トレイトを使用すると、ファクトリートレイトを、共通の系統を持たない複数のクラス階層間で共有できるという利点があります。

<?php

// NOTE: traits are only avaialable in ** PHP 5.4 **
trait Factory 
{
    public static function createObject() 
    {
        echo get_class() . "<br/>";        // prints ChildClass
        echo get_called_class() . "<br/>"; // prints ChildClass
        return new static();
    }
}

class ChildClass
{
    use Factory;

    private $greeting = "bye";

    private function __construct()
    {
        $this->greeting = "hi";
    }

    public function greet()
    {
        echo $this->greeting;
    }
}

$child = ChildClass::createObject();
$child->greet();

作業コードの例

于 2012-08-21T06:18:28.280 に答える