开发者

PHP - Class that can be instantiated only by another class

Imagine this scenario:

class Page {}

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

Is there anyway i can make sure on开发者_C百科ly objects of my class Book can instantiate Page? Like, if the programmer tries something like:

$page = new Page('pagename');

the script throws an exception?

Thanks


It's a bit contrived, but you could use this:

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


Well, I see your point, but with the tools provided by the language, this is not possible.

One thing you could do, is require a Book object when constructing a Page:

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

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


I think that the most you can get, is to have Page demand Book as one of it's constructor arguments, and have it add page to this instance of Book. This way you never have Pages floating around, but they're always bound to some book (although it's still possible to have same Page in many Books.

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

That looks ugly though... :/


No. In PHP, it's not possible. Even if it would be possible, developer could modify to his own needs and disable your exeption...

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜