我有两个类A
,并且B
都继承自同一个父级。在 PHP 中,有没有办法确保B
除了在类中之外不能实例化该类A
?
(类B
不是 的孩子A
。)
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
^^.
是的。
如何实现它是,让 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
你可以在这里看到一个演示。
我不是从 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...