我有两个类A
和B
,都来自同一个父级。在PHP中,有没有办法确保除了B
类之外的类A
无法实例化?
(班级B
不是A
的孩子。)
答案 0 :(得分:4)
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
设为私有^^。
答案 1 :(得分:1)
我不是从PHP的角度考虑这个问题,而是从oop方面考虑更多......想想你能实现它的唯一方法就是你将B的构造函数设为私有,然后公开一个接受A参数的静态方法然后该方法可以私有地实例化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 ......
答案 2 :(得分:1)
是
如何实现它是,让类B
的构造函数接受一个参数。并为类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
您可以看到演示here。