7
votes

PHP - classe qui peut être instanciée uniquement par une autre classe

Imaginez ce scénario:

$page = new Page('pagename');


3 commentaires

Pourquoi? c'est une mauvaise pratique.


Celui-ci est effectivement lié à Python, mais je pense que cela s'applique très bien: "Nous consentissons tous des adultes ici".


Pourquoi est-ce une mauvaise pratique @Daniel?


4 Réponses :


5
votes

Eh bien, je vois votre point, mais avec les outils fournis par la langue, cela n'est pas possible.

Une chose que vous pourriez faire, nécessite un objet de livre lors de la construction d'une page: P>

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

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


2 commentaires

Merci pour votre réponse, cela m'aide en quelque sorte. Je vais devoir accepter @genesis réponse, pour des raisons évidentes


Pourquoi? Je vous ai dit que ce n'était pas aussi possible, et j'ai fourni une solution alternative: P



1
votes

non. En PHP, ce n'est pas possible. Même si cela serait possible, le développeur pourrait modifier ses propres besoins et désactiver votre exception ...


1 commentaires

Ceci est vrai bien sûr, mais alors quel est le point dans laquelle vous attendez quelque chose de vos classes / interfaces du tout? Je pense que vous vous attendez généralement à ce que d'autres développeurs ne touchent pas votre bibliothèque de classes s'ils veulent les utiliser ou ne garantissent tout simplement pas le résultat attendu s'ils vont altérer. Quoi de plus; Si vous publiez une mise à jour de votre bibliothèque, ils devront les modifier à nouveau, ainsi que de nouveau, etc.



3
votes

Je pense que le plus que vous puissiez obtenir, est d'avoir page code> demande book code> comme l'un des arguments du constructeur de son constructeur et qu'il a ajouté une page à cette instance de livre. Cette façon, vous n'avez jamais de page code> s flottant autour, mais ils sont toujours liés à un livre (bien qu'il soit toujours possible d'avoir la même page code> dans de nombreux book Code> 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);
  }
}


0 commentaires

5
votes

C'est un peu conçu, mais vous pouvez utiliser ceci:

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 );


2 commentaires

Oui, c'est un peu conçu mais fait exactement ce que je demandais. Merci beaucoup


Intelligent! Et cela ne soulève même pas aux erreurs de niveau E_STRICT s'il est activé.