我有两个类A和B,它们都继承自同一个父类。在PHP中,有没有一种方法可以确保只能在类A中创建类B的实例,而在其他地方创建类B的实例将导致错误?(注意:类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();
}
编辑:如果您想确保在A
的代码内部创建B
,也可以这样做 - 只需将buildB
设为私有即可。
我并不是从 PHP 的角度考虑这个问题,而是更多地从面向对象编程的角度思考... 我认为你能够实现它的唯一方法就是将 B 的构造函数设为私有,然后暴露一个静态方法,该方法接受 A 的参数和 B 的输出参数,然后该方法可以私下实例化 B 并通过输出参数将其返回给 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,因此如果您封闭该类(防止子类),那将关闭该门。
这是一个有趣的问题...
编辑:这个模块确实没有解决问题,但也许(?)它更好了 - 我为B创建了一个以A作为参数的公共构造函数,并且现在只在A中进行B的实例化。唯一的问题是它仍然存在JDelage指出的同样的问题 - 如果我实例化A,我可以构建一个B...
是的。
您可以通过使类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
$i
。我不明白$i
是做什么的。 - JDelage
A
中。我正在编辑标题,因为它不够明确。 - JDelagebuildB()
方法设为私有,然后你就完成了^^ - moonwave99