nloding Posted August 24, 2007 Share Posted August 24, 2007 I decided to put this in a new topic ... here's the issue I've come across, and I've not tested the code so I'm not sure what it'll do ... figured I'd ask while I was coding, since the last topic of factories brought some good conversation. You create a parent class that implements an interface. Then you create a child class that extends the parent. Does the child class need the functions the interface dictates? I assume no, since the parent already has them and the 'implements' keyword isn't used in the child line. But, by definition "When inheriting from an abstract class, all methods marked abstract in the parent's class declaration must be defined by the child" and by definition, all methods in an interface are abstract ... I still think the child class doesn't need them. Am I right? Here's the code example of what I'm asking: <?php interface myInterface { function duh($wee); function oops($uhoh); } class FakeClass implements myInterface { public function duh($wee) { // ... } public function oops($uhoh) { // ... } } class FakeKid extends FakeClass { public function notFromInterface($canIDoThis) { // ... } private function alsoNotInTheInterface($isItPossible) { // ???????? } // but there are no other functions from the interface here! } Quote Link to comment Share on other sites More sharing options...
keeB Posted August 24, 2007 Share Posted August 24, 2007 That's perfectly acceptable, since FakeKid extends FakeClass (which Implements myInterface) , FakeKid has really defined the 2 functions which myInterface is expecting. The only caveat is, though, since you have not declared FakeClass functions protected they CAN be overwritten by child objects. Quote Link to comment Share on other sites More sharing options...
matthewhaworth Posted August 24, 2007 Share Posted August 24, 2007 Where can I find a practical example of this? Quote Link to comment Share on other sites More sharing options...
nloding Posted August 24, 2007 Author Share Posted August 24, 2007 Check back tonight ... hopefully I'll have one! Quote Link to comment Share on other sites More sharing options...
nloding Posted August 25, 2007 Author Share Posted August 25, 2007 LONG post ahead! Here is why I started this thread -- to make sure I could extend the database class how I wanted. I'm trying to abstract as much code as I can ... <?php /** * database_v2.inc * * Making greater strides towards understanding design patterns and OOP * encapsulation. I'm trying very, very hard to get a strong set of db * objects that can used in a factory pattern; this is forced practice * to better understand all the principals involved. * * The point of this exercise is to design a database class that abstracts * as much of it's code as possible into child classes. */ // The interface (i.e., the design of the parent object) interface dbInterface { function connect($host, $user, $pass, $dbname); function query($query); function insert($table, $items, $values); function update($table, $to_update, $where); function execute($query); function fetchAssoc($result); function fetchArray($result); function fetchObject($result); function disconnect(); } class dbParent implements dbInterface { private $conn; private $lastResult; private $numQueries; protected function __construct() { $this->lastResult = NULL; } protected function connect($host, $user, $pass, $dbname) { $this->conn = new mysqli($host, $user, $pass, $dbname); } protected function query($query) { $this->lastResult = $this->conn->query($query); $this->numQueries++; } protected function insert($table, $items, $values) { $query = "INSERT INTO " . $table . " " . $items . " VALUES " . $values; $this->conn->query($query); $this->numQueries++; } protected function update($table, $to_update, $where) { $query = "UPDATE " . $table . " SET " . $to_update . " WHERE " . $where; $this->conn->query($query); $this->numQueries++; } protected function execute($query) { $this->conn->query($query); $this->numQueries++; } protected function fetchAssoc($result = NULL) { if($result == NULL) $result = $this->lastResult; if($result == NULL || $result->num_rows < 1) { return NULL; } else { return $result->fetch_assoc(); } } protected function fetchArray($result = NULL) { if($result == NULL) $result = $this->lastResult; if($result == NULL || $result->num_rows < 1) { return NULL; } else { return $result->fetch_array(); } } protected function fetchObject($result = NULL) { if($result == NULL) $result = $this->lastResult; if($result == NULL || $result->num_rows < 1) { return NULL; } else { return $result->fetch_object(); } } protected function disconnect() { $this->conn->close(); } } class dbUser extends dbParent { // User related database functions, such as active users or registering } class dbSecurity extends dbParent { // Security related database functions, such as comparing user/pass } class dbForum extends dbParent { // Forum related database functions, such as posting and viewing threads } All this generated by a factory, with a variable that defines what is called. I'm not gonna paste it here, but basically you call Factory::getInstance('Security') and it calls 'dbSecurity' by doing "db" . $type; That's where I'm headed with this whole thing ... I hope it works, I like the way it sounds in my head. Quote Link to comment Share on other sites More sharing options...
hostfreak Posted August 26, 2007 Share Posted August 26, 2007 The only problem I see with it is that the methods that the interface implement will have to have a public scope. Although, you'd figure that out soon enough and my post has nothing to do with your original question, just thought I'd mention it. Quote Link to comment Share on other sites More sharing options...
nloding Posted August 26, 2007 Author Share Posted August 26, 2007 Yeah, they'd have to public. That's the point of a database class ... to provide a wrapper for the database functions for other functions, methods, classes, objects, dogs, cats, and programmers to use. Besides, all methods declared in the interface must be public ... Quote Link to comment Share on other sites More sharing options...
hostfreak Posted August 26, 2007 Share Posted August 26, 2007 Yes, I am aware of that. As of now, what you have wont work. The methods implemented by the interface, implemented in the "dbParent" class must be public. Quote Link to comment Share on other sites More sharing options...
keeB Posted August 26, 2007 Share Posted August 26, 2007 protected is also fine, hostfreak. Quote Link to comment Share on other sites More sharing options...
hostfreak Posted August 26, 2007 Share Posted August 26, 2007 Ah ic. Ha, talk about feeling stupid ATM. Thanks for setting me straight keeB. Sorry nloding. Quote Link to comment Share on other sites More sharing options...
hostfreak Posted August 27, 2007 Share Posted August 27, 2007 Actually, no, I was right. It must be public. See as I said in my previous post, that code will give you errors. Anytime you use an interface the methods must be "public" not only in the interface, but in the class that implements the interface as well. Quote Link to comment Share on other sites More sharing options...
448191 Posted August 28, 2007 Share Posted August 28, 2007 LONG post ahead! Here is why I started this thread -- to make sure I could extend the database class how I wanted. I'm trying to abstract as much code as I can ... <?php /** * database_v2.inc * * Making greater strides towards understanding design patterns and OOP * encapsulation. I'm trying very, very hard to get a strong set of db * objects that can used in a factory pattern; this is forced practice * to better understand all the principals involved. * * The point of this exercise is to design a database class that abstracts * as much of it's code as possible into child classes. */ // The interface (i.e., the design of the parent object) interface dbInterface { function connect($host, $user, $pass, $dbname); function query($query); function insert($table, $items, $values); function update($table, $to_update, $where); function execute($query); function fetchAssoc($result); function fetchArray($result); function fetchObject($result); function disconnect(); } class dbParent implements dbInterface { private $conn; private $lastResult; private $numQueries; protected function __construct() { $this->lastResult = NULL; } protected function connect($host, $user, $pass, $dbname) { $this->conn = new mysqli($host, $user, $pass, $dbname); } protected function query($query) { $this->lastResult = $this->conn->query($query); $this->numQueries++; } protected function insert($table, $items, $values) { $query = "INSERT INTO " . $table . " " . $items . " VALUES " . $values; $this->conn->query($query); $this->numQueries++; } protected function update($table, $to_update, $where) { $query = "UPDATE " . $table . " SET " . $to_update . " WHERE " . $where; $this->conn->query($query); $this->numQueries++; } protected function execute($query) { $this->conn->query($query); $this->numQueries++; } protected function fetchAssoc($result = NULL) { if($result == NULL) $result = $this->lastResult; if($result == NULL || $result->num_rows < 1) { return NULL; } else { return $result->fetch_assoc(); } } protected function fetchArray($result = NULL) { if($result == NULL) $result = $this->lastResult; if($result == NULL || $result->num_rows < 1) { return NULL; } else { return $result->fetch_array(); } } protected function fetchObject($result = NULL) { if($result == NULL) $result = $this->lastResult; if($result == NULL || $result->num_rows < 1) { return NULL; } else { return $result->fetch_object(); } } protected function disconnect() { $this->conn->close(); } } class dbUser extends dbParent { // User related database functions, such as active users or registering } class dbSecurity extends dbParent { // Security related database functions, such as comparing user/pass } class dbForum extends dbParent { // Forum related database functions, such as posting and viewing threads } All this generated by a factory, with a variable that defines what is called. I'm not gonna paste it here, but basically you call Factory::getInstance('Security') and it calls 'dbSecurity' by doing "db" . $type; That's where I'm headed with this whole thing ... I hope it works, I like the way it sounds in my head. If I may butt in... Why is there a dbInterface? May I suggest the following alternative: <?php abstract class DbAbstract { protected $conn; protected $lastResult; protected $numQueries; public function __construct($host, $user, $pass, $dbname) { $this->connect($host, $user, $pass, $dbname); } public function query($string){ $this->lastResult = $this->doQuery($string); $this->numQueries++; } public function insert($table, $items, $values) { $this->doInsert($table, $items, $values); $this->numQueries++; } abstract function doQuery($string); abstract function doInsert($table, $items, $values); abstract function connect($host, $user, $pass, $dbname); } class DbMySQLi extends DbAbstract { public function connect($host, $user, $pass, $dbname) { $this->conn = new mysqli($host, $user, $pass, $dbname); } public function doQuery($query) { return $this->conn->query($query); } public function doInsert($table, $items, $values) { $query = "INSERT INTO " . $table . " " . $items . " VALUES " . $values; $this->conn->query($query); } } abstract class DAO { protected $dbObject; public static function factory($rdbms, $domain, $host, $user, $pass, $dbname){ $daoClass = $domain.'DAO'; $dbClass = 'Db'.$rdbms; return new $daoClass(new $dbClass($host, $user, $pass, $dbname)); } } class UserDAO extends DAO { public function __construct(DbAbstract $dbObject){ $this->dbObject = $dbObject; } public function getActiveUserCount(){ $this->dbObject->query('SELECT count(id) FROM users WHERE active = "1"'); //etc... return $count; } } $userDao = DAO::factory('MySQLi', 'User', 'localhost', 'root', '', 'cms'); echo 'Active users: '.$userDao->getActiveUserCount(); ?> Look into Layer Supertype [PoEAA: 475]. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.