2011-08-22 22 views
6

Imagínese este escenario:PHP - Clase que se pueden crear instancias únicamente por otra clase

class Page {} 

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

¿Hay alguna forma de asegurarse de que sólo los objetos de mi clase de libro puede crear una instancia página? Al igual que, si el programador intenta algo como:

$page = new Page('pagename'); 

la secuencia de comandos se produce una excepción?

Gracias

+1

por qué eso es una mala práctica –

+1

éste está realmente relacionado con Python, pero creo que se aplica muy bien:?. "Estamos todos los adultos que consienten aquí ". –

+1

¿Por qué es una mala práctica @ Daniel? –

Respuesta

4

es un poco artificial, pero se puede usar esto:

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í, es un poco artificial, pero hace exactamente lo que estaba pidiendo. muchas gracias –

+0

@ André: De nada. Buena pregunta por cierto; votado. –

+0

¡listo! E incluso no aumenta los errores de nivel E_STRICT si está habilitado. – Mchl

4

Bueno, veo su punto, pero con las herramientas proporcionadas por el lenguaje, esto no es posible.

Una cosa que podría hacer, es un objeto requiere libro al construir una página:

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

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

gracias por su respuesta, me ayuda un poco. Voy a tener que aceptar la respuesta de @genesis, por razones obvias –

+0

¿Por qué? Te dije que no era posible y proporcioné una solución alternativa: P – Rijk

+0

tienes razón, lo siento. No había visto su primer párrafo –

1

No. En PHP, no es posible. Incluso si fuera posible, el desarrollador podría modificar sus propias necesidades y deshabilitar su excepción ...

+1

Esto es cierto, por supuesto, pero entonces ¿cuál es el punto de esperar algo de sus clases/interfaces en absoluto? Creo que generalmente espera que otros desarrolladores no toquen su biblioteca de clases si quieren usarlas, o simplemente no garantizan el resultado esperado si van a manipularlo. Lo que es más; si emite una actualización a su biblioteca, tendrán que modificarla una y otra vez, etc. –

2

Creo que lo máximo que puede obtener es tener Page demanda Book como uno de sus argumentos de constructor, y tenerlo agregar página a esta instancia de Libro. De esta manera nunca tiene Page s flotando alrededor, pero siempre está obligado a algún libro (aunque todavía es posible tener Page misma en muchos 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); 
    } 
} 

Eso se ve mal, aunque ...:./

+0

sí, no cumple mi propósito, pero está cerca. gracias –

Cuestiones relacionadas