私には2つのクラス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
は、同様に行うことができます -buildB
プライベートにするだけです ^^.
私はこれを 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 を構築できます...
はい。
それを達成する方法は、クラス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
ここでデモを見ることができます。