Page 1 of 1
Working with several classes - Extend or reference?
Posted: Wed Oct 05, 2005 1:45 pm
by StumpDK
I think I need an advice...
I have a project (PHP 4) in which I have 3 different classes: Database, Validator and Authorize.
Every class have its own responsibilities, but some times, I'll need the classes to work together.
An example:
I'll check if a user have logged in. Therefore I'll use the Authorize-class. But I'll have to connect to the database to check if the user exists. And I'll have to use the Validator-class to check if the user-submitted information is correct.
So I can't create the Authorize-class by extending it from the Database-class because I'd still need the Validator to control the data handled by Validator-class.
How do I do it?
Posted: Wed Oct 05, 2005 2:16 pm
by Ree
My suggestion is leave them separate as they are now. In Authorize class you can create an instance of the Database class (probably in constructor) and then use it to your needs to check whatever data in the db you need. Validation object you will of course use before Authorization, and there's really no need to combine them in a single class.
Posted: Wed Oct 05, 2005 4:51 pm
by McGruff
Definitely no inheritance. The objects have different roles: use inheritance sparingly, and only when a derived class is is the same "thing" as the superclass, with a couple of extra bells and whistles.
Encapsulation does create the problem of how to get all these separate objects talking to each other. Read up as much as you can about design patterns for some ideas.
Posted: Thu Oct 06, 2005 8:08 am
by StumpDK
So the right way to do it is this:
Code: Select all
include('database_class.php');
class Authorize{
function checkUserLogin(){
$db = new Database;
$db->dbConnect();
//Do the login check
}
}
But is this 'correct' OOP?
Posted: Thu Oct 06, 2005 12:27 pm
by zwxetlp
The general rule I use for inheritance vs inclusion is the 'is a/has a' rule.
Use inheritance when the new class 'is a' more specific or otherwise special object of the type of the superclass, and use inclusion when the new class contains ('has a') instance of the other class.
Posted: Thu Oct 06, 2005 1:27 pm
by McGruff
StumpDK wrote:So the right way to do it is...
Yes. You might find that several objects need to use the $db object, in which case you would pass it in, probably as a constructor parameter.
Posted: Thu Oct 06, 2005 4:14 pm
by StumpDK
As a constructor parameter?
Posted: Thu Oct 06, 2005 4:51 pm
by Nathaniel
StumpDK wrote:As a constructor parameter?
Code: Select all
<?PHP
class Authorize
{
var $db;
//Class Constructor
// Automatically called on $auth = new Authorize($db);
function Authorize(&$db)
{
$this->db =& $db;
}
}
?>
Make sense?
- Nathaniel
Posted: Thu Oct 06, 2005 5:37 pm
by StumpDK
So you create the Database-object first, and then call the constructor of the Authorize-class with a reference to the Database-object?
By doing that I only have to create one Database-object for every page, since I can use the same database-class in all other classes that needs it...
Am I right?
Posted: Thu Oct 06, 2005 7:25 pm
by sweatje
StumpDK wrote:So you create the Database-object first, and then call the constructor of the Authorize-class with a reference to the Database-object?
By doing that I only have to create one Database-object for every page, since I can use the same database-class in all other classes that needs it...
Am I right?
Yep.
Since your Authorize class needs the Database Connection, it is "dependant" on the DbConn. You could just create it where needed, but this is limiting. What you have done in that case is hard code in the only possible value for the dependancy. If you want to be able to vary the dependancy, then you have three options.
a) constructor injection (you have seen an example of this already)
b) method injection- which looks like this insize the Authorize class:
Code: Select all
function setConn(&$conn) {
$this->db =& $conn;
}
or c) attribute injection - with public attributes:
Code: Select all
$auth =& new Authorize;
$auth->db =& $conn;
Even though the language allows it, I like to pretend my attributes are all private, therefore that leaves a or b as options, of which I tend to lean towards a.
HTH
Posted: Fri Oct 07, 2005 3:15 am
by Maugrim_The_Reaper
I've run up against this problem recently - I find a few classes needing to be used within others on a very regular basis - typically Database, Configuration, Template.
Needing to pass these as parameters becomes difficult when every script requiring them is and of itself an object (Command pattern). Now given the number of this parameters can vary as the project progresses, and not all Commands need the same number of objects in order to operate. What are everyone's view on utilising the Singleton to access objects within other objects? I think this works fine for many single instance objects, but are there major downsides to using a similar tactic for say DB?
To explain to StumpDK...
A Singleton allows an object to be called from any other object using a static getInstance() method. For example:
Code: Select all
<?php
class FrequentlyUsed {
function FrequentlyUsed() {
}
function &getInstance() {
static $thisInstance;
if($thisInstance == null)
{
$thisInstance = new FrequentlyUsed();
}
return $thisInstance;
}
}
class NeedsFrequentlyUsed {
var $frequentlyUsed;
function NeedsFrequentlyUsed() {
$this->frequentlyUsed =& FrequentlyUsed::getInstance();
}
function execute() {
$this->frequentlyUsed->method();
}
}
?>
A singleton method re-uses the same instance of a class, i.e. it returns a reference to the whatever class it is included with - no copies.
Posted: Fri Oct 07, 2005 6:26 am
by sweatje
The Singleton pattern still exhibits on of the main problems the dependancy injection get around: you have hard coded the dependancy into the class and therefore shot yourself in the foot by not allowing polymorphism. Singletons are good for ensuring access to a common single instance without using a global variable, but they still pose subtler dangers. Use with caution.