3

私には2つのクラスAとがありB、どちらも同じ親から継承しています。PHPでは、クラスB内以外からクラスをインスタンス化できないようにする方法はありますAか?

(クラスBはの子ではありませんA。)

4

3 に答える 3

4

debug_backtrace の使用:

class Ancestor{}

class A extends Ancestor{

    public function buildB()
    {

        return new B;

    }

}

class B extends Ancestor{

    public function __construct(){

        $backtrace = debug_backtrace();
        if( $backtrace[1]['class'] !== 'A' )
            throw new Exception("Don't you dare!");

        echo "Built successful!\n";

    }

}

それを試してみてください:

//Everything ok this way:
$a = new A;
$a -> buildB();

// You will have an exception in any other case:
try{

    $b = new B; 

}catch(Exception $e){

    echo $e -> getMessage();

}

B編集: のコードのすぐ内側に確実に作成したい場合Aは、同様に行うことができます -buildBプライベートにするだけです ^^.

于 2012-09-13T18:56:21.237 に答える
1

私はこれを php の観点から考えているわけではありませんが、もっと oop 側から考えています...それを達成できる唯一の方法は、B のコンストラクターをプライベートにしてから、A のパラメーターと out を受け入れる静的メソッドを公開することだと思いますB のパラメーターである場合、そのメソッドは B をプライベートにインスタンス化し、out パラメーターを介して A に返すことができます。

//Pseudocode, language-indifferent

    class A{
       var _B;

       public B GetMeAnInstanceOfB(){
          _B=B.CreateInstanceOfB(this);
       }

       //alternate
       public B GetMeAnotherInstanceOfB(){
          _B=new B(this);
       }
    }

    class B{
       private B();
       //alternate
       private B(A);
       static B CreateInstanceOfB(A){
          return new(b);
       }
    }

それは本当に大雑把で、おそらく甌穴でいっぱいですが、それには刺し傷があります. 技術的には、A のサブクラスは B を取得する可能性があるため、クラスを封印すると (サブクラスが防止されます)、そのドアは閉じられます。

確かに興味深い質問です...

編集:この mod は実際には問題を解決しませんが、おそらく (?) より良いです - A をパラメーターとして取る B のパブリック コンストラクターを作成し、B のインスタンス化は A でのみ行われるようになりました。唯一の問題は、JDelage が指摘した同じ問題が続くことです。A をインスタンス化すると、B を構築できます...

于 2012-09-13T18:40:08.837 に答える
1

はい。

それを達成する方法は、クラスBのコンストラクターが1つの引数を受け入れるようにすることです。Aのオブジェクトを作成するクラスのメソッドを定義しますB

$argument == null||の場合、終了または例外をスローします。!($argument instanceof A).

コード例:

class X {
    public $i = 0;
    public function getI() {
        return $i;
    }
    public function setI($x) {
        $i = $x;
    }
}

class A extends X {
    public function setI($x) {
        $i = $x * 2;
    }
    public function makeB($var){
        $b = new B($var);
    }
}

class B extends X {
    public function __construct($a) {
        if (null == $a) {
            echo "no arguments given!\r\n";
            //exit;
        }else if (!($a instanceof A)) {
            echo "disallowed\r\n";
            //exit;
        }else{
            echo "initialized b\r\n";
        }
    }
    public function setI($x) {
        $i = $x * 3;
    }
}

$a = new A();

$a->makeB();
$a->makeB(new X());
$a->makeB(&$a);

出力:

Warning: Missing argument 1 for A::makeB(), called in file.php
no arguments given!
disallowed
initialized b

ここでデモを見ることができます。

于 2012-09-13T18:46:14.400 に答える