3

我有两个类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's 代码中创建,你也可以这样做 - 只需将buildB^^.

于 2012-09-13T18:56:21.237 回答
1

是的。

如何实现它是,让 classB的构造函数接受一个参数。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 回答
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确实不能解决问题,但也许(?)更好 - 我已经为B创建了一个公共构造函数,它以A作为参数,并且B的实例化现在只发生在A中。唯一的问题是它仍然存在 JDelage 指出的相同问题 - 如果我实例化 A,我可以构建一个 B...

于 2012-09-13T18:40:08.837 回答