tags:

views:

132

answers:

3

I have a class like:

<?PHP

abstract class dbCon
{
    public function OpenConnection()
    {
          // Do Something;
          // On error:
          $this->ShowError();
    }
    abstract function ShowError();
}

class ErrorHandling extends dbCon
{
    public function ShowError()
    {
        // Show error
    }
}
?>

There is a flaw in the above code. I want to call ShowError() from within abstract class but it is where the interface defined. How to deal this?

+3  A: 

You're confusing inheritance with delegation. ErrorHandler should really be a delegate of dbCon.

One useful way of determining if a class A should be a subclass of B is to ask yourself if saying "A is a more specific kind of thing than B is." That is, does A have at least all the basic attributes and behaviors of B. An example of where this is true, and also is not:

  1. TRUE: A cougar is a type of feline.

  2. FALSE: A trunk is a type of car.

  3. FALSE: A lawyer is a type of record label executive.

In case 2, a truck is part of a car, so the correct way to model this is by composition; have a Car object that can then contain a reference to a Trunk object.

In case 3, a lawyer is a delegate of the record label executive; the correct way to model this is by having your RLExective object hold a reference to one or more Lawyers it knows, and have the RLExecutive call the SueCollegeStudentOrGrandmother() method on any one of the Lawyers when the need arises.

In your hierarchy here, you are saying that ErrorHandler is a type of dbCon. This doesn't make any sense. It would be more accurate to say that ErrorHandler is a delegate of dbCon, tasked with handling errors. In this case, you would probably want a freefloating ErrorHandler object, or maybe one with specific knowledge about DB errors. Whenever dbCon gets an error it wants to display, it throws the error over to ErrorHandler via the ShowError() method.

Based on your comment, it seems your confusion lies in the meaning of extends. By saying ErrorHandler extends dbCon, you have said that ErrorHandler is a subclass of dbCon, not that ErrorHandler adds additional functionality to dbCon. This means you would have to create an instance of ErrorHandler, which would have both the functionality of dbCon and ErrorHandler. This is probably not what you want.

Hope this made some sense.

Ed Carrel
@Ed: Exactly that I want. dbCon must handle that delegate, but are you talking about PHP or .NET?
RPK
If by .NET you mean c#, it makes little difference. The keyword extends means the same thing in either language. It looks like you are working in PHP here, given the syntactic clues, and I answered with PHP in mind originally. :-)
Ed Carrel
A: 

I suggest you to read about Polymorphism.

The invocation of ShowError() from the parent class will be determined by the class of the instance and this is done at runtime.

To demonstrate, consider this code:

<?PHP

abstract class dbCon {
    public function OpenConnection() {
          // Do Something;
          // On error:
          $this->ShowError();
    }
    abstract function ShowError();
}

class ErrorHandling extends dbCon {
    public function ShowError() {
        // Show error
        echo "Error is here\n";
    }
}
class WarningHandling extends dbCon {
    public function ShowError() {
        // Show waring
        echo "Warning is here\n";
    }
}

$ErrorHandling = new ErrorHandling();
$ErrorHandling->OpenConnection();

$WarningHandling = new WarningHandling();
$WarningHandling->OpenConnection();

?>

When run, you will get:

Error is here
Warning is here

Why?

Because, the first ShowError() is from an object of ErrorHandling type. PHP sees that the object is from a concrete type ErrorHandling so when ShowError() is called from OpenConnection, php use the function from the object type (ErrorHandling).

The second ShowError() call is from an object of WarningHandling so PHP is using the ShowError() of WarningHandling.

Take a look at Polymorphism carefully. Polymorphism is one of the most important concept of OOP (as it is only one missing from Object-based oriented).

Hope this helps.

NawaMan
In case your answer ends up a fold or more above mine -- congrats if it does, btw --, that something called ErrorHandling is opening a connection to anywhere should give a developer pause. The first thing I would think of is maybe a connection to a logging system somewhere else, but in this model it could be to any arbitrary database who's interaction might result in errors. Conceptually odd ideas like this should be a warning sign.
Ed Carrel
I think if this is the case, it is not good to call the OpenConnection() via an instance of ErrorHandling. What will be the right approach?
RPK
@Ed Carrel: Yes, I agree that this is an odd design decision. But it is not the point here. What I am trying to show is that parent object can call an abstract method. The actual execution will be determined based on the concrete class in which the object is created from. This is the whole point of polymorphism.
NawaMan
@Rohit: It is totally fine calling OpenConnectio() of an instance of ErrorHandling as ErrorHandling is inherit (see expands) from dbCon so it has the method as well. And ShowError in OpenConnectio() will be the one from ErrorHandling. This is by no means that I thin this is an appropriate design. Ed Carrel is right about that point (which I am not arguing). Cheer!
NawaMan
+1  A: 

You could implement your own exception handler:

class Exception_Handler extends Exception {
    ...
}

class DB_Connection {
    try {
        throw new Exception_Handler('Cannot connect to DB: ' . $exception->getMessage() . '.');
    } catch (Exception_Handler $exception) { $exception->show(); }
}

More on this: http://www.w3schools.com/php/php_exception.asp

Radek