Just because some strange possibilities exists with PHP 5 object language
doesnt mean it is very often anything useful.
Some few times, however it may simplify a special case for someone
So it does not hurt it is there.

Or maybe many of you use Abstract classes and Interfaces all the time???
Maybe I am one of the few, that doesnt
đŸ™‚

    m"Just because some strange possibilities exists with PHP 5 object language
    doesnt mean it is very often anything useful.

    Or maybe many of you use Abstract classes and Interfaces all the time???
    Maybe I am one of the few, that doesnt
    "

    Abstract classes/interfaces are very very useful. I don't think you are one of the few who doesn't but at some point they will become more useful. Pagination for one is something I find really really really mind numbingly boring and I wrap it up.

    Things that are constant settings/calculations that can be wrapped in a concrete paginator class.
    1 . Set an object by interface to handle any actions this class has calculated as needed.
    2 . Set current page
    3 . Set total pages
    4 . Set the desired range ( ie 5 )
    5 . Start - recalulate everything is in range( start page, current_page etc )
    6 . Calculate the start page index, create the end page index so you can go 4,5,6,7,8,9 ( the desired range set above )
    7 . Call the method/methods that start the handling of actions on the object set by interface below.

    Things that can be called back by the class set by interface and handle site specific stuff.
    1. Tell the object set by interface whether any pagination is needed. Then that object knows nothing else is going to happen if it is false and take appropriate action.
    2. Tell the object set by interface we need a back button and add one. //As it's not concrete it can be an image, english text, french text doesn't matter. The paginator class doesn't know and doesn't care.
    3. Call the object set by interface repeatedly with any page numbers from the start page index to the end page index.
    4. Tell the object set by interface object we need a forward button and add one.

    Whether there needs to be 10 sets of pagination links or just 1 that is up to the interface object to handle when called back via one of its methods. The paginator class doesn't know or care enough about it.

    Wrapping it up like this locks the mathmatical aspects in a way that is hopefully bug free away from the site specific logic. If it isn't you will soon know about it as it replicates everywhere and is easy to fix.

      mpb, that sounds pretty awesome. I've been meaning to do that for awhile. It's really helpful to have a class for paging because you can have convenient methods for screening GET/POST input for the correct values, etc. I'd love to get a peek at that if you wouldn't mind?

        OK...I'm having one of those programmer awakening mind contortions here. Bounçable sounds fabulous if I was writing games, but can we use the idea of a website asset as an example? This is what I'm actually wrestling with.

        The custom CMS I've been roped into working on has this concept of 'asset' which can be an audio file, a logo image (small 100x100 image), a photo (large image), or a video. has a variety of functions that let you attach an asset to a variety of things: a user account, a company, your mom, etc. Each asset has an associated file (or sometimes two: e.g., cropped and raw logos) which is located somewhere. There is also a table, 'asset' which is used to logically connect these assets to the various other data entities.

        I've been mulling this over for awhile now and seems to me I should probably create an abstract class called 'Asset' which would perhaps implement a method or two to create the db records and then specify some abstract methods such as getFilePath which would return the full file system path to an image and getWebPath which would return the apache path to an object for use in html. Maybe like the ones below...i have some questions in there so I'd appreciate it if you could take a peek for me:

        Asset

        abstract class Asset{
        
          protected $db; // reference to pear db object
          protected $validator; // object containing validation primitives
          protected $id = NULL; // the id from the db table
          protected $type = NULL; // specifies whether logo, audio, video, photo
          protected $fileName = NULL; // the name of the file
          /* other db fields blah blah blah */
        
        
          /* all child classes will have to implement these */
          abstract public function getWebPath(); // apache path for html display
          abstract public function getFilePath(); // actual filesystem path
          abstract public validateMedia(); // checks file format, size, etc.
        
          public function __construct($dbConnection){
            $this->db             = $dbConnection;
        
        require_once(SERVER_CLASSES."/Validator.php");
        $this->validator        = new Validator($this->db);
          }
        
          public function createDBREcord() {
            // code here validates properties and attempts to store in a new DB record
            // sets $this->id to last_insert_id
          }
          public function updateDBREcord() {
            // code here validates properties and updates an existing DB record
          }
          public function save() {
            if (is_null($this->id)) {
              $this->createDBREcord();
            } else {
              $this->updateDBREcord();
            }
          }
        
        }
        

        Then an Image class would extend asset

        class Image extends Asset {
          public $width = NULL;
          public $height = NULL;
          public $format = NULL; // GIF, JPG, PNG, etc.
        
        
        
          public function getWebPath() {
            return WEB_IMAGE_PATH . $this->fileName; // the const is defined in site config file
          }
          public function getFilePath() {
            return FS_IMAGE_PATH . $this->fileName; // the const is defined in site config file
          }
          public validateMedia() {
            // i reckon i would use PECL extensions to check mime type or something
          }
        
          public function __construct($dbConnection){
            // would i need to override the construct of abstract class?  can I?
          }
        
          public function crop(x, y, w, h) {
          }
          public function resize(w, h) {
          }
        }
        

        And finally Logo extends Image

        class Logo extends Image {
          const MAX_WIDTH = ASSET_LOG_MAX_WIDTH; // defined in sitewide config;
          const MAX_HEIGHT = ASSET_LOG_MAX_HEIGHT; // defined in sitewide config;
        
          public function __construct($dbConnection){
            // is there any way to call the Asset constructor here? I just want to add some code to it?
          }
        
          public function dimensionsAreOK() {
            if ($this->width > self::MAX_WIDTH) {
                return false;
            }
            if ($this->height > self::MAX_HEIGHT) {
                return false;
            }
        
        return true;
          }
        
        }
        

        I don't really see any need for interfaces in this scheme. They just seem like gelded abstract classes. Just extra hassle. Speaking of hassle, where does one keep all these interfaces? In the same folder as your classes? [man]Autoload[/man] doesn't work on these does it?

          Autoload does indeed work with interfaces. Does not seem to be explicitly documented under autoload but it is under the interface-exists function. http://us2.php.net/manual/en/function.interface-exists.php

          As far as your example goes, if it makes sense for all objects that act as assets to be derived from the same base class then use an abstract class.

          It's when you have different sorts of objects for which you want to share some common behavior that interfaces start to become important. Suppose we have a resource scheduler program. Resources might include people, locations and equipment. They all need to be scheduled but should people really share the same base class as equipment and locations? Probably not. So one might develop a Schedule_Resource interface.

            sneakyimp wrote:

            mpb, that sounds pretty awesome. I've been meaning to do that for awhile. It's really helpful to have a class for paging because you can have convenient methods for screening GET/POST input for the correct values, etc. I'd love to get a peek at that if you wouldn't mind?

            Should be with you if this private message thing works.

              Supposing I create a construct method in my abstract class, Asset. Is it then possible to define a construct in some extending class (say Image) which calls the __construct class of Asset plus a few extra lines.

              i.e., does this work as a constructor in the Image class if the Asset class has a constructor function?

              class Image extends Asset {
                function __construct() {
                  parent::construct();
                  // more code here blah blah blah
                }
              }
              
                sneakyimp wrote:

                Supposing I create a construct method in my abstract class, Asset. Is it then possible to define a construct in some extending class (say Image) which calls the __construct class of Asset plus a few extra lines.

                i.e., does this work as a constructor in the Image class if the Asset class has a constructor function?

                class Image extends Asset {
                  function __construct() {
                    parent::construct();
                    // more code here blah blah blah
                  }
                }
                

                Yes, except don't forget the underscores:

                parent::__construct();
                

                đŸ™‚

                  Hm. It just occurred to me that it's a bit inconvenient to have described those abstract methods in my Asset class because this would require that they get defined in the Image class which directly extends Asset. This isn't very convenient because an Image could be a Logo or Photo and I store these files in different locations. A Logo knows where it is located but an Image would have to perform additional checks to determine whether it is Photo or Logo.

                    sneakyimp wrote:

                    ...because this would require that they get defined in the Image class which directly extends Asset

                    unless you declare Image itself as abstract. At which point you're asking yourself just what sorts of Images you have and creating a subclass for each.

                    But that's not 100% necessary. Even if you have written an implementation for a method then unless you've declared it final you can have subclasses overriding it with something more appropriate. So a generic method could be written for more generic classes, and more specific versions for subclasses.

                    ahundiak's mention of type hinting shouldn't go past unremarked.

                    Say you have objects that may have comments attached. They're a varied bunch, these commentable objects - some are images, some are text, some are people, maybe it's even possible to attach comments to comments. Then you have a bunch of functions for operating on a given object's comments.

                    Even if the commentable objects have no comment-related methods (unlikely, but possible), it's still worthwhile declaring a Commentable interface (even if it's empty), and having commentable objects implement it. Any of these comment-handling functions that expects a commentable object to be passed to it can be stated as expecting a commentable object

                    function do_something_with_comments(Commentable $foo) {...}

                    If at some point you booboo and try passing something that's not Commentable to do_something_with_comments() you'll get an error that refers you to the point at which you call the function. Without the type hint the error will come at some arbitrary point later in the function (or in one of the functions called by it) and you'll be left having to crawl through the stack trace wondering how you got into the mess. It's like having a front door that refuses to open for you if you are naked (and tells you to go put some clothes on), instead of letting you out into the street and leaving you to be arrested.

                      I find GWT really good for understanding this stuff as it is a more formal wrapper being a java to javascript convertor but all google's java source code is visible and consistent in approach( well more consistent then me anyway). I find it easier to read code then the philosophical discussions about ducks. I have a design patterns book that goes on far to much about ducks. More useful and understandable if I was writing a game involving ducks.

                      A lot of the time interfaces are used for the controlling of events and other things outside of the direct timeline( like callbacks ).

                      
                      //pseudocode
                      abstract class Image
                      {
                      
                      }
                      
                      
                      
                      class OnloadListeningImage extends Image implements OnloadListener
                      {
                      
                      function onload()
                      }
                      
                      
                      absract class Button
                      {
                      
                      }
                      
                      
                      class OnloadListeningButton extends Button implements OnloadListener
                      {
                      
                      function onload()
                      }
                      
                      
                      I then have a handling class that is automatically called on page load
                      
                      class OnloadHandler 
                      {
                          listeners = array();
                      
                      function addOnloadListener( (OnloadListener) onloadListener )
                      {
                          listeners[] = onloadListener;
                      }
                      
                      //Iterate through all the onload listening objects triggering their onload actions when called
                      function notifyLoadingHasFinished()
                      {
                          for( i = 0 ; i < listeners.length ; i ++ )
                          {
                              listeners[ i ].onload();
                          }
                      }
                      }
                      
                      
                      Now I can go
                      
                      onloadListeningImage = new OnloadListeningImage();
                      onloadListeningButton = new OnloadListeningButton();
                      
                      onloadHandler = new OnloadHandler();
                      onloadHandler.addOnloadListener( onloadListeningImage );
                      onloadHandler.addOnloadListener( onloadListeningButton );
                      
                      
                      if we were following this model in javascript we'd go
                      
                      window.onload = onloadHandler.notifyLoadingHasFinished;
                      or
                      window.onload = function()
                      {
                         onloadHandler.notifyLoadingHasFinished();
                      }
                      
                      

                      Sometimes you will want actions to only happen after the window has finished loading, ie the button becomes enabled from disabled the image goes from displaying "loading..." to something else such as invisible. Both actions can be completely different from each other due to they are defined by interfaces. Even within there type of say Button one button could go blue, one button could bounce around the page the OnloadHandler doesn't care.

                      It can be a bit hard to get to grips with in PHP due to it is synchronous, however many discussions I read about it the answer for comes from looking at a working real life code example. Ignore the 22 pages on ducks, dogs and everthing else that can distract from the simplicity and the ideology. It is like when I started writing classes and one day after a while the simplicity of implementation and organisation really sunk in. Organisation is something I don't always see as implementation is always the more obvious thing that gets learnt far more day in and day out. But organisation is actually far more important and interfaces are a tool purely for organisation due to they define no implementation.

                        Ok...the docs are a bit vague when it comes to an abstract class extending another abstract class. That child abstract class doesn't need to define those abstract methods from the parent abstract class. In other words, this causes an error:

                        abstract class class1 {
                          abstract public function someFunc();
                        }
                        abstract class class2 extends class1 {
                          abstract public function someFunc();
                        }
                        

                        Error: Fatal error: Can't inherit abstract function class1::someFunc() (previously declared abstract in class2) in /home/sneakyimp/public/chump.php on line 7

                        However this does not:

                        abstract class class1 {
                          abstract public function someFunc();
                        }
                        abstract class class2 extends class1 {
                        }
                        

                        An abstract class that extends an abstract class can pass the buck to its child classes when it comes to implementing the abstract methods of its parent abstract class. Thanks weedpacket for pointing that out.

                        In my current implementation, rather than making my Image class abstract, I have defined stub versions of the methods required by the parent Asset class. These stubs just throw an exception telling me that these methods need to be overridden by a child class. In retrospect, this sounds pretty stupid so I'll probably make image abstract now. Why wait til runtime to get a fatal exception?

                        As for ahundiak's point, I am familiar with strongly-typed languages but was under the impression PHP is loosely typed. Since when does PHP allow type enforcement in function declarations? I kicked around the php.net site a bit looking for evidence of this but haven't found any yet. And not just type enforcement but you can specify an interface? What sorts of things can you enforce for your function arguments? Where are the docs on this?

                          Right on. Thx mpb. Interesting to note the docs don't mention interfaces but the comments do. Those PHP documentation writers are getting lazy.

                            Write a Reply...