SitePoint Sponsor

User Tag List

Results 1 to 16 of 16
  1. #1
    SitePoint Zealot
    Join Date
    May 2001
    Posts
    193
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Interface Vs. Abstract and Inheritance

    In an attempt to understand interfaces, and abstract classes I downloaded creole and checked out their use of them.
    I am confused!
    I took a look at the interface, abstract, and derived classes for a Prepared Statement.

    PreparedStatementCommon.php which is the abstract class contains about 28 methods of which only 1 is declared as abstract escape($str)

    PreparedStatement.php is the interface class which declares 27 of the methods implemented in the abstract class.

    MySQLPreparedStatement.php is a derived class which extends the abstract which implements the interface and implements the method escape().

    My question is why bother with the abstract class in this example, why not just add the 1 abstract method to the interface, and make PreparedStatementCommon.php into a regular class.

    Im having trouble seeing the value of the abstract class here.

    Thanks for any input

    Also, I was reading a another post and there was a link to an article talking about "Why extends is evil", sorry can't remember the thread. But the jist of it was don't use inheritance or avoid it at all costs, and opt for Interfaces instead. I don't understand, how do you acheive what extends gives you using an interface, since you can't implement anything in the interface. There was a quote saying somethng to the affect, "80 percent of your code should be wriiten in terms of interfaces...".

  2. #2
    SitePoint Evangelist
    Join Date
    Dec 2003
    Location
    Arizona
    Posts
    411
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    What I got out of the "Extends is Evil" article is that the author was an advocate of interface inheritance over implementation inheritance.

    PHP Code:
    // Base class
    class {
        function 
    a() {
        }

        function 
    b() {
        }
    }

    // Implementation Inheritance
    class extends {
        function 
    a() {
        }

        function 
    b() {
        }

        function 
    c() {
        }
    }

    // Interface Inheritance
    interface {
        function 
    a();
        function 
    b();
    }

    class 
    implements {
        function 
    a() {
        }

        function 
    b() {
        }
    }

    // Interface Inheritance
    class implements {
        var 
    $b;

        function 
    C() {
            
    $this->= new B();
        }

        function 
    a() {
            
    $this->b->a();
        }

        function 
    b() {
            
    $this->b->b();
        }

        function 
    c() {
        }

    The private instance of the pseudo-superclass kind of reminds me of the GoF Proxy pattern.

    Here is an article, also from JavaWorld, on choosing between abstract classes and interfaces:

    http://www.javaworld.com/javaworld/j...-abstract.html

    Thanks,

    JT

  3. #3
    SitePoint Zealot
    Join Date
    May 2001
    Posts
    193
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Yes, I got the same thing from that article, but it seems to me it's not an either/or type of choice. I mean, if I have some common methods for a base class, I need to extend this base in order to inherit these methods, which would mean the base class would either need to be an abstract or regular class and not an Interface, since you can't implement anything in an interface.

    So, I don't understand saying "you should avoid inheritance..." and use Interfaces, I don't see how an interface is an alternative to extending a base class, when you need some common methods of the base.

  4. #4
    Employed Again Viflux's Avatar
    Join Date
    May 2003
    Location
    London, On.
    Posts
    1,130
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    My understanding goes like this...

    If all the methods in your abstract class are abstract, then you have an interface. Otherwise, you have an abstract class.

  5. #5
    SitePoint Evangelist
    Join Date
    Dec 2003
    Location
    Arizona
    Posts
    411
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by MikeShank
    Yes, I got the same thing from that article, but it seems to me it's not an either/or type of choice. I mean, if I have some common methods for a base class, I need to extend this base in order to inherit these methods, which would mean the base class would either need to be an abstract or regular class and not an Interface, since you can't implement anything in an interface.

    So, I don't understand saying "you should avoid inheritance..." and use Interfaces, I don't see how an interface is an alternative to extending a base class, when you need some common methods of the base.
    You don't need to extend the base class to get some common methods from a base class as with class "C" in my example. You drag around a private instance of the class that you want common functionality out of (in the case of the example, that is class "B").

    JT

  6. #6
    SitePoint Zealot
    Join Date
    May 2001
    Posts
    193
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Red face

    Thanks, now Im really confused.

    What is the advantage to that type of inheritance,
    I mean couldnt you do the same thing with a regular class,
    instead of extending just
    PHP Code:
    class 
     var 
    $b

     function 
    C() { 
     
    $this->= new B(); 
     } 

     function 
    c() { 
     } 

    I guess what im getting at is, what is so bad about extending a class?

    Is it more about writing perfect code, because I often extend classes, it seems like a natural thing to do, it makes sense, and most of all it works.
    The stuff I work on is simple sites, cms's and the like, and stuff like this sometimes seems like real overkill, I mean the more threads, catch phrases, pattern names, etc.. I read, the more it seems to me I spend more time trying to conform to these things than attacking the problem.

  7. #7
    Non-Member
    Join Date
    Oct 2004
    Location
    downtown
    Posts
    145
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I guess what im getting at is, what is so bad about extending a class?
    Can't remember the exact reasoning behind 'Inheritance is bad' though I do believe that is't discussed in 'Thinking In Java'?

    Just don't ask what Chapter, it's an indepth read

  8. #8
    SitePoint Evangelist
    Join Date
    Dec 2003
    Location
    Arizona
    Posts
    411
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I say "do what works for you". If you are using implementation inheritance and it works well for you don't worry about the "Extends is Evil" article. I would definitely not advise that you try to conform your implementation to a particular design pattern. Really what you should do is implement and if you recognize something in your code that can be solved with a pattern, then use the pattern. If anything, adapt the patterns implementation to fit your particular problem but not the other way around.

    Thanks,

    JT

  9. #9
    SitePoint Zealot
    Join Date
    May 2001
    Posts
    193
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Does 'Thinking In Java' translate into Thinking In PHP, i mean do the same rules apply? I assume you use inheritance, since you can't remember the reason that you shouldn't.

    Sorry if I'm coming off thick here, I don't have a formal programming background and I get overwhelmed sometimes with all of the patterns, concepts, etc..
    thanks for your help

  10. #10
    SitePoint Wizard DougBTX's Avatar
    Join Date
    Nov 2001
    Location
    Bath, UK
    Posts
    2,498
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by seratonin
    I would definitely not advise that you try to conform your implementation to a particular design pattern.
    The article isn't talking about a design pattern, it is just a description of an idea. That idea may or may not be used in a particular design pattern, but that's not what the article is about.

    If you read the comments at the bottom, you'll see lots of voices against the "is evil" line - and taking such an extreme view probably isn't very clever. If you want to extend an implementation, then extends is the thing to use. If you want to extend an interface, but have the freedom to change the implementation, then that's what this article is talking about.

    One of the ideas is that it is better to reuse a class as a black box rather than to try and make the black box bigger. If the black box is small to start with (say, an abstract class) then this argment isn't very strong.

    If you have a class which does xy, and you want it to do z too, then you may as well extend it to do xyz. If, later, you wanted to replace xy with ab, you'd be stuck. So, one solution is to have z accept a class which could do ab or xy depending on what object is passed to it. That's where "extends is evil" because you'd probably have to duplicate z into xy and ab.

    Or, you could turn the whole thing on its head, and pass z to ab or xy, and they can work out what to do with their new features themselves. Then you could pass in q instead of z, making abq and xyq without having to tell ab or xy what they are doing

    Look up the GoF Composite and Stratagey patterns for more ideas.

    Douglas
    Hello World

  11. #11
    SitePoint Wizard DougBTX's Avatar
    Join Date
    Nov 2001
    Location
    Bath, UK
    Posts
    2,498
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by MikeShank
    Does 'Thinking In Java' translate into Thinking In PHP, i mean do the same rules apply?
    Not always. Some things fall under 'Thinking in OO', in which case they can apply to PHP and Java. Differences in the languages themselves (strong typing in Java vs dynamic typing in PHP) does make some difference. As far as variables are concrened, there could really be anything behind that $ sign. This gives you quite a bit of flexibility because you don't have to know what you are going to set the variable to before you set it. That's often useful, you may not always know what a variable is even once you've got a copy of it

    Douglas
    Hello World

  12. #12
    Resident Java Hater
    Join Date
    Jul 2004
    Location
    Gerodieville Central, UK
    Posts
    446
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Personally, I don't see extends as "evil", but like any technique in programming, it can be misused and called "evil" because many use it incorrectly (look at goto, that is evil, but there are case in languages like C++ where using a forward goto is cleaner and more readable than a load of flagging varaibles/tests to break out of loops).

    The big issue with extending classes is that if you are not careful, you will nearly always use inheritance. This is particularlly bad in bigger projects as you will end up with the classes that are on the leaves of your class trees extending a hell of a lot of classes. If you follow that class up to the root base class in your tree, you need to look and compare the two classes. In bigger projects if you are extending a lot, then many times you will find that extending classes leaves you in a position where the leaf classes often end up not having much in common with your root most base class. However that class will still need to implement a lot of the methods from the base class, etc etc. In these situation the leaf classes are probably not using half the the methods that is has inherited, and if they are then, most of those methods are completely reimplemented in the extended classes, and thus your root / base class in the class tree has little in common with the leaf classes, even though if you comapre a class and it's parents there will still be a strong relationship.

    The other issue with inheritance is that in the real world, many objects will implement a number of interfaces. Look at a car, that has electrical and mechanical properties and a novice C++ programmer might see the easy way to model this is by making a electrical and mechanical as classes, and then making the car extend both of these classes. In this situation, use of inheritance is a possible solution that works, even if it's not the most suitable. We can get away with multiple inheritance here as we know exactly what classes we are extending from.

    However there are times were this is not possible. Take a look at a person. We might need to deal with two types of people who have different skills. One might be a a Web Designer, and the other might be a programmer...

    class WebDesigner extends Person {}
    class Programmer extends Person {}

    Now in the real world, people don't just have one skill like illistrated above. Take me for example, I am both a web designer and computer programmer... With multiple inheritance I could say ....

    class Jason extends WebDesigner, Programmer {}

    but PHP won't let me. The other thing, unlike the car where the classes we extend from is predictable, when it comes to the person example, things change. A person during it's lifetime will learn new skills. For instance I might learn how to drive, or a might learn how to snowboard or something. These new skills can not be added to me at runtime via inheritance. As a result inheritance fails. Instead of inheriting, it becomes better to use aggregation. A good example of this is the Decorator pattern. I could demonstrate this by doing....

    $Jason = new Snowboarder(new Driver(new Programmer(new WebDesigner(new Person())));

    Now Snowboarders, Drivers, Programmers and Web Designers are classes that know and work with people. So they might implement the Person interface.

    e.g.

    interface IPerson {
    function hasSkills();
    function gender();
    }

    from this Person interface we can make a concrete class called Person. This is abstract as the class is incomplete (a person must have a concreate gender)

    abstract class Person implements IPerson {
    function hasSkills () {
    return array('talk', 'walk', 'eat'); //Skills all normal people have ;-)
    }

    abstract function gender() {
    }
    }

    Let make out concrete classes for a Person

    class Male extends person() {
    function gener() {
    return 'Male';
    }
    }

    class Male extends person() {
    function gener() {
    return 'Stupid Female';
    }
    }

    now classes like WebDesigner, Programmer, etc know a bit about a Person but they only deal with certain features relating to a Person, and they are not aware of other Skills and as classes do not deal anything relating to a person such as their gender or other skills that person may have. This means we can make a skelton class for this, this will be our decorator class.... (Note this is abstract as is it can not be instanced as an object as it not "complete")

    abstract class PersonDecorator implements IPerson {
    public $wrapper;

    function __construct(IPerson &$person) {
    $this->wrapper = $person;
    }
    function gender() {
    $this->wrapper->gender();
    }
    function hasSkills() {
    $this->wrapper->hasSkills();
    }
    }

    now from this class we can create skills....

    class WebDesigner extends PersonDecorator {
    function hasSkills() {
    $skills = parent::hasSkills();
    $skills[] = 'Web Design';
    return $skills;
    }
    }

    class Programmer extends PersonDecorator {
    function hasSkills() {
    $skills = parent::hasSkills();
    $skills[] = 'Programmer';
    return $skills;
    }
    }

    ... etc.

    now with this, you could model someone like me like this....

    $Jason = new WebDesigner(new Programmer(new Male()));

    Interfaces are needed to state what behaviours are common to a number of classes. However behaviours differ majorly ...

    for example

    interface IOpenAble {
    function Open();
    }

    class Door implements IOpenAble {}
    class File implements IOpenAble {}

    Open is a behaviour common to Door and File, but you woudln't have an abstract base class (ABC) here as both these methods are implmented totally differently when it comes to their algorithm.

    The ABC is used in may example for classes like Decorators where there is behaviour that is shared. It is quite common to mix interfaces and ABC's like I had IPerson and Person.

    Inheritance was also used in my example. However my example is designed in such a way that inheritance is doesn't create big class trees. If you inherit classes more than 3 or 4 times that is a bad code smell and therefore is *normally* avoidable.

    The nice thing is that I can creat an object, such as $Jason, myself, and I can have the properties of Male, WebDesigner and Programmer without using multiple inheritance. Likewise if I was to develop new skills or for some reason, it doesn't cause problems in my design...Let say I took up snow boarding

    $Jason = new SnowBoarder($Jason);

    No problem.

    The nice thing is that the Skill classes do not need to bound to a specific person class, as long as the object has implements IPerson. This means if our model was to be extended in the future, it would easily accomodate this. We could easily add something stupid like a Transvestite Gender, without having to affect the Skill classes.

    The issue comes when Web Designer has extra methods and Programmer has extra methods as these are not callable if I take up snow boarding. In Java I think DynamicProxies get round this. In PHP5 you can use

    function __call($func, $params)
    {
    return call_user_func_array(array($this->wrapper, $func), $params);
    }

    in the PersonDecorator class.

    Look at the SPL in PHP5. It shows off the use of interfaces and decorators very well. The other thing to look at for interfaces is the DOM API. DOM uses interface and factories a lot. The idea of the interface plays a big part here where the composite pattern is used heavily. Interfaces and factories in the DOM API allow for it to be easy to create different implementions of the DOM (i.e. so it can be used with CSS, and HTML etc as well as XML).

  13. #13
    SitePoint Evangelist
    Join Date
    Dec 2003
    Location
    Arizona
    Posts
    411
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by DougBTX
    The article isn't talking about a design pattern, it is just a description of an idea. That idea may or may not be used in a particular design pattern, but that's not what the article is about.
    My comment was in response to:

    Quote Originally Posted by MikeShank
    The stuff I work on is simple sites, cms's and the like, and stuff like this sometimes seems like real overkill, I mean the more threads, catch phrases, pattern names, etc.. I read, the more it seems to me I spend more time trying to conform to these things than attacking the problem.
    It wasn't specifically directed towards the article "extends is evil" but using design patterns, idioms, or "best practices" in general and trying to *conform* your solution or implementation to them.

    JT

  14. #14
    SitePoint Member AlexBrina's Avatar
    Join Date
    Jul 2004
    Location
    office.bh.mg.br
    Posts
    23
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Hi,

    MiiJaySung, your post was really helpful and lightened some shadows here, that would be nice if I could just do somenthing like:
    PHP Code:
     $alex = new OOPMaster$alex 
    but as a novice in this subject I tend to think simpler, due to lack of knowledge or experience. In you example, the only implementation I could think of would be: a person has skills, so this method "addSkill( $skill )" goes in the person class to fill up the $skill array.

    What would be the advantages of your implementation using the Decorator opposed to mine in this case ... If you ask me to read more about OO and patterns I'll understand you
    Alex Brina
    "...sempre q eu tirar a cabeça fora d'agua eu dou um alô..." JC

  15. #15
    Resident Java Hater
    Join Date
    Jul 2004
    Location
    Gerodieville Central, UK
    Posts
    446
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    $alex = new OOPMaster( $alex )

    Should work as you want it as the parameter $alex will be passed to the constructor of OOPMaster, and you would do something like $this->something = &$alex; which means the value of alex will referenced by both $this->something and $alex (otherwords both these variables are pointing to the same thing and is $alex changes, $this->something will change with it). When the constructor exits, $alex get told to point to the new object you've pointed. $this->something however should still point to the old $alex object. In order how to understand the way variables get controlled you need to understand references well. Whenever I teach this to other people in person, I often use the example of a files system where you have file data and a file name. The filename is like a variable name, and the contents of the file is like the variable value. What links them together is that the file name is linked specificly to those file contents. Another words the filename is referencing some file contents. This is done on the file system my holding where the file physically exists. This concept is exactly the same with varibables. When you make hard links on the UNIX file system (where two files names point to the same file contents), this is like having two variables referencing the same value / location in memory. The main concept behind referencing is the notation of a named item having a pointer (anotherwords it describes a location / address in some way).

    Personally I would stick to different variable names to remove this confusing notation though ....

    $new_alex = &new OOPMaster($alex);

    .... is easier to see this distiction.

    What would be the advantages of your implementation using the Decorator opposed to mine in this case
    Well I don't know what your implementation is refering to as such. As far as design goes, different patterns are good in different situations, and although the decorator is very good/useful there are times when inheritance, and other methods are better. However the big mistake of many OOP newbies is that they often overlook common basic patterns like iterators and decorators, and seem to get hooked on doing everything using inheritance by extending classes. As a result, a number of more experienced programmers will swing towards telling newbie to use these patterns more often. It's also why a number of people say things like inheritance is evil, blah blah, blah. This is not the case imo. It's just a matter of using the right pattern for the task. As Marcus / Lastcraft pointed out, patterns should be seen as tools in a toolbox, you should know how to use them, but not use them for the sake of using them to get something done. You wouldn't use a hammer to unscrew something, as that would be using the wrong tool for the task. Patterns are the same. You will find as you get used to OOP, using the right patterns will come naturally.

  16. #16
    SitePoint Member AlexBrina's Avatar
    Join Date
    Jul 2004
    Location
    office.bh.mg.br
    Posts
    23
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    ok, you wrote in your post...
    $Jason = new SnowBoarder($Jason);
    No problem.
    so, that "$alex = new OOPMaster( $alex )" was supposed to be funny, I was making a metaphore about how my life could be easier if all I needed to do to learn OOP were writing that statement and voila now I know OOP
    PS: maybe u did not get what I meant due to my poor english, if so, excuse me (getting better each time I come here)

    My implementation was poor explained in my post. What I would do to represent that a Person has Skills would be:
    PHP Code:
    class Skill{}
    class 
    OopKnowledge extends Skill{}
    class 
    Person {
      var 
    $skills = array();
      function 
    addSkill( &$skill ) {
        
    $this->skills[] =& $skill;
      }
    }

    $person =& new Person();
    $person->addSkill( new OopKnowledge() ); 
    In you code you needed to write this:
    PHP Code:
    abstract class PersonDecorator implements IPerson {
    public 
    $wrapper;

    function 
    __construct(IPerson &$person) {
    $this->wrapper $person;
    }
    function 
    gender() {
    $this->wrapper->gender();
    }
    function 
    hasSkills() {
    $this->wrapper->hasSkills();
    }

    that made me see that a Decorator actually IS a wrapper for a class, to add some different feature or behavior to the class... My problem is that when I'm designing a solution I hardly see a situation where this pattern fits in, I always think that an aggregation works right. Do you have any example of a real need for the Decorator. Pehaps its a matter of style, I don't know. We can solve a problem with different tools from the toolbox but which problem is solved better with the Decorator.
    Alex Brina
    "...sempre q eu tirar a cabeça fora d'agua eu dou um alô..." JC


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •