2011-08-22 12 views
6

Wyobraźmy sobie następujący scenariusz:PHP - klasa, która może być instancja tylko przez inną klasę

class Page {} 

class Book { 
    private $pages = array(); 
    public function __construct() {} 
    public function addPage($pagename) { 
     array_push($this->pages, new Page($pagename)); 
    } 
} 

Czy mimo to mogę upewnić się tylko obiekty moja klasa książka może instancję stronę? Na przykład, jeśli programista próbuje coś takiego:

$page = new Page('pagename'); 

skrypt zgłasza wyjątek?

Dzięki

+1

dlaczego ów złe praktyki –

+1

Ten jest rzeczywiście związane z pytona, ale myślę, że odnosi się bardzo dobrze? „. wszyscy jesteśmy tolerancyjni partnerzy tutaj " –

+1

dlaczego jest to zła praktyka @Daniel? –

Odpowiedz

4

to trochę wydumane, ale można użyć to:

abstract class BookPart 
{ 
    abstract protected function __construct(); 
} 

class Page 
    extends BookPart 
{ 
    private $title; 

    // php allows you to override the signature of constructors 
    protected function __construct($title) 
    { 
     $this->title = $title; 
    } 
} 

class Book 
    extends BookPart 
{ 
    private $pages = array(); 

    // php also allows you to override the visibility of constructors 
    public function __construct() 
    { 
    } 

    public function addPage($pagename) 
    { 
     array_push($this->pages, new Page($pagename)); 
    } 
} 

$page = new Page('test will fail'); // Will result in fatal error. Comment out to make scrip work 

$book = new Book(); 
$book->addPage('test will work'); // Will work. 

var_dump($book); 
+0

tak, jest nieco wymyślone, ale robi dokładnie to, o co prosiłem. bardzo dziękuję –

+0

@ André: Nie ma za co. Przyjemne pytanie przy okazji; przegłosowane. –

+0

Sprytny! I nawet nie podnosi błędów poziomu E_STRICT, jeśli jest włączony. – Mchl

4

Dobrze, rozumiem twój punkt widzenia, ale z narzędzi dostarczonych przez język, to nie jest możliwe.

Jedno można zrobić, to wymaga obiektu Book przy konstruowaniu Strona:

class Page { 
    public function __construct(Book $Book) {} 
} 

class Book { 
    public function addPage() { 
     $this->pages[] = new Page($this); 
    } 
} 
+0

dzięki za odpowiedź, to mi pomaga. Będę musiał zaakceptować odpowiedź @genesis z oczywistych powodów. –

+0

Dlaczego? Powiedziałem ci, że to też nie jest możliwe i dostarczyłem alternatywne rozwiązanie: P – Rijk

+0

masz rację, przepraszam. Nie widziałem twojego pierwszego akapitu –

1

Ilość w PHP, to nie jest możliwe. Nawet gdyby było to możliwe, programista może modyfikować swoje własne potrzeby i wyłączyć wyjątek ...

+1

To oczywiście prawda, ale po co w ogóle oczekiwać niczego od twoich klas/interfejsów? Sądzę, że generalnie oczekujesz, że inni deweloperzy nie dotkną twojej biblioteki klas, jeśli zechcą z niej skorzystać, lub po prostu nie gwarantują oczekiwanego rezultatu, jeśli zamierzają się z tym pogodzić. Co więcej; jeśli wydasz aktualizację swojej biblioteki, będzie musiała zmodyfikować je ponownie, i znowu, i znowu, itd. –

2

Myślę, że najbardziej można uzyskać, to mieć Page żądanie Book jako jeden z jego argumentów konstruktora i mieć go dodaj stronę do tego wystąpienia Book. W ten sposób nie musisz Page s pływających wokół, ale oni zawsze wiąże się z pewnym książki (choć nadal można mieć taką samą Page w wielu Book s

class Book { 
    public function addPage($page) { 
    if(is_a($page,'Page') { 
     $this->pages->push($page); 
    } else if (is_string($page)) { 
     new Page($this,$page) 
    } else { 
     throw new InvalidArgumentException("Expected string or 'Page' - ".gettype($page)." was given instead"); 
    } 
    } 
} 

class Page { 
    public function __construct(Book $book, $pagename) { 
    $book->addPage($this); 
    } 
} 

który wygląda brzydki choć ...: /.

+0

tak, nie służy to mojemu celowi, ale jest blisko. dzięki –

Powiązane problemy