Nate
Nate

Reputation: 577

php enforce type of extending class

Is there any way in php to make sure that a class can be extended by one and only one class?

I have some code that illustrates what I'm trying to do, basically I have a DB manager class and a DB query class that is extended by the manager class. What I'd like to do is make sure that the DB query class can only be used by the DB manager class.

The code below works, but it seems very rough. In the code I delcare the query class abstract with a single abstract function that checks the classname, or I could simply declare all of the Manager functions as abstract in the query class (which seems hacky). If there is a simpler way to do this than my code below that would be very useful...

abstract class DB_Query {

    private static $HOST = 'localhost';
    private static $USERNAME = 'guest';
    private static $PASSWORD = 'password';
    private static $DATABASE = 'APP';


//////////
/* USING ABSTRACT FUNCTION HERE TO ENFORCE CHILD TYPE */

abstract function isDB();

/* OR USING ALTERNATE ABSTRACT TO ENFORE CHILD TYPE */

    abstract function connect();
    abstract function findConnection();
    abstract function getParamArray();
//////////


    private function __construct() { return $this->Connect(); }
    public function Read($sql) { //implementation here }
    public function Query($sql) { //implementation here }
    public function Fetch($res, $type='row', $single='true') { //implementation here }

}

class DB extends DB_Query {

    public $connections = array();
    public static $instance;

    public function isDB() {
        if (get_parent_class() === 'Database' && get_class($this)!=='DB') {
            throw new \Exception('This class can\'t extend the Database class');
        }
    }

    public function connect($host=null,$user=null,$pass=null,$db=null) { //implementation here }
    function findConnection($user, $password=null) { //implementation here }
    public function getParamArray($param) {}
    public function threadList() {}
    public function getThread($threadId=null) {}
    public static function Singleton() { //implementation here }
    private function __construct() { //implementation here }

}

Upvotes: 0

Views: 116

Answers (2)

Nate
Nate

Reputation: 577

class Database_Query extends Database {

    public static $instance;
    public function Query($sql) {}
    public function Fetch($res, $type='row', $single='true') {}
    public static function Singleton() {}

    private function __construct() {
        $this->link = $this->connect()->find('guest')->getLink();
    }

}

Upvotes: 0

Segabond
Segabond

Reputation: 1143

I would go after marking the constructor of DB_Query as final and implementing it the way that it checks the instance and fires some exception. Something like this

class Base {
    final function __construct() {
         if (!$this instanceof Base && !$this instanceof TheChosenOne) {
               throw new RuntimeException("Only TheChosenOne can inherit Base");
         }

         /**
          * use this function as constructor
          */
         $this->__internal_base_construct();
    }

    protected function __internal_base_construct() {
     // constructor code
    }
}

But your problem is rather strange and kind of breaking the idea of OOP in several ways. Just combine it into a single class and use final class directive.

http://php.net/manual/en/language.oop5.final.php

Upvotes: 2

Related Questions