2011-08-22 13 views
6

Immaginate questo scenario:PHP - classe che possono essere istanziati solo da un'altra classe

class Page {} 

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

C'è qualche cosa che posso fare in modo solo gli oggetti della mia classe Book possibile creare un'istanza di pagina? Come, se il programmatore cerca qualcosa di simile:

$page = new Page('pagename'); 

lo script genera un'eccezione?

Grazie

+1

perché questo è cattiva pratica –

+1

questo in realtà è legato al pitone, ma penso che si applica molto bene:?. "Siamo tutti adulti consenzienti qui " –

+1

perché è una cattiva pratica @Daniel? –

risposta

4

è un po 'forzato, ma è possibile utilizzare questo:

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

sì, è un po 'inventato ma fa esattamente quello che stavo chiedendo. grazie mille –

+0

@ André: prego. Bella domanda, a proposito; upvoted. –

+0

Intelligente! Inoltre, non aumenta gli errori di livello E_STRICT se abilitato. – Mchl

4

Beh, vedo il tuo punto, ma con gli strumenti forniti dal linguaggio, questo non è possibile.

una cosa che si possa fare, è richiede un oggetto Book quando la costruzione di una pagina:

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

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

grazie per la tua risposta, mi aiuta un po '. Dovrò accettare la risposta @genesis, per ovvi motivi –

+0

Perché? Ti ho detto che non era possibile, e ho fornito una soluzione alternativa: P – Rijk

+0

hai ragione, mi dispiace. Non avevo visto il tuo primo paragrafo –

1

n In PHP, non è possibile. Anche se fosse possibile, lo sviluppatore potrebbe modificare le sue esigenze e disabilitare la tua eccezione ...

+1

Questo è vero, naturalmente, ma allora qual è il punto in attesa di qualcosa dalle tue classi/interfacce? Penso che generalmente ti aspetti che altri sviluppatori non tocchino la tua libreria di classi se vogliono usarle, o semplicemente non garantiscono il risultato atteso se vogliono manometterle. Cosa c'è di più; se si rilascia un aggiornamento alla propria libreria, dovranno modificarli nuovamente, e ancora, e ancora, ecc. –

2

Penso che il massimo che puoi ottenere sia avere Page richiesta Book come uno dei suoi argomenti del costruttore, e averlo aggiungi una pagina a questa istanza di Book. In questo modo non dovrete mai Page s in giro, ma sono sempre legato a qualche libro (anche se è ancora possibile avere lo stesso Page in molti 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); 
    } 
} 

che sembra brutto anche se ...:./

+0

sì, non è funzionale al mio scopo, ma è vicino. grazie –

Problemi correlati