回答
我不是從PHP的角度思考這一點,但更多的從空中接力身邊...想你可以做到的唯一事情是這樣的,如果您將B的構造函數設爲private,然後公開一個接受A參數和B out參數的靜態方法,然後該方法可以私有實例化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 ...
是的,我正在研究PHP,但問題實際上是語言不可知的。這是一個很酷的想法,你在這裏。我喜歡。 – JDelage
如果語言不可知,則在'A'中定義嵌套的私有類'B'。不幸的是,這[用PHP無法完成](http://stackoverflow.com/questions/1548286/can-you-have-nested-classes-in-php)。然而,在SO上發佈了一些解決方法。 – Josh
@Josh非常有效的觀點,但是OP確實說明B不是A的孩子,所以我對這個定義採取了一點自由,以免嵌套。我知道嵌套不會讓他們成爲面向對象的層級意義上的孩子,但是將它們分開在OP提供的上下文中是有效的。 –
是。
您如何去實現它,使課堂B
的構造函數接受一個參數。並定義一個方法A
,使B
的對象。
死亡或擲execption如果$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。
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
私人^^。
哦,很好。我不會想到這一點。 – JDelage
我會做一些測試,看看debug_backtrace()是否足夠好,這是一個可行的解決方案。否則,如果沒有這個要求,你可能會更好。從一般的觀點來看,解耦的代碼比緊密耦合的代碼更好,並且強制執行這個要求違背了這個基本原則。話雖如此,你的具體情況可能需要這個要求,但如果我設計這個,我會考慮一個不同的類結構。 –
@ moonwave99,雖然這是一個聰明的做法 - +1 –
- 1. 有沒有辦法確定一個類是Java中的一個實例?
- 2. Ruby - 有沒有辦法獲得一個特徵類的實例?
- 3. 有沒有辦法獲得一個類的工廠實例?
- 4. 有沒有一種方法讓ActiveRecord返回其他類的實例,而不是一個查找被調用?
- 5. 有沒有辦法選擇一個類的特定元素?
- 6. 有沒有辦法區分一個案例類和一個Tuple?
- 7. 有沒有辦法繞過一個沒有實現Serializable的類?
- 8. 實例中沒有一個類的ARFF
- 9. 有沒有辦法使用GWT.create(...)來實例化一個泛型類的類?
- 10. 有沒有辦法阻止一個特定的孩子觸發SIGCHLD?
- 11. 有沒有辦法爲一個類的實例定義[]運算符?
- 12. 有沒有辦法在不調用__init__的情況下實例化一個類?
- 13. 實例化一個沒有「新」的類
- 14. 有沒有辦法從一個元素獲得SlickGrid的實例
- 15. C++:有沒有辦法指定一個從另一個繼承的泛化類?
- 16. 如何從其他沒有實例的類中調用方法?
- 17. 阻止類被實例化
- 18. 有沒有辦法有一個模板類(所有類型的)一個靜態變量不破壞封裝
- 19. 沒有安裝一個特定設備
- 20. Xcode實例方法沒有被另一個類調用
- 21. 有沒有辦法檢查一個CustomAction失敗而不中止安裝?
- 22. 有沒有辦法停止從flash_mp3_player的其他播放器實例播放mp3?
- 23. 有沒有辦法阻止同一網頁上的其他ReportViewer刷新?
- 24. 有沒有一種方法,以新的一類,它是同類型的其他類沒有直接指定它
- 25. 有沒有辦法阻止派生類進一步實現虛擬功能?
- 26. 有沒有辦法阻止一個類使用靜態斷言和類型特徵兩次派生?
- 27. 好的做法是從另一個不是兒童的類中找到一個類的現有實例
- 28. 有沒有辦法將一個類的特定值綁定到數據網格?
- 29. 有沒有辦法用測試數據創建一個類型的實例?
- 30. 有沒有什麼辦法來實例化一個匿名的內部類?
您是否希望B僅在**類'A'內部實例化[即從'A'的方法]還是'A'的實例? – moonwave99
@ moonwave99 - 只在'A'內。我在編輯標題,這是不明確的。 – JDelage
查看我的關於編譯'buildB()'方法的私人編輯,你完成了^^ – moonwave99