Page 1 of 2 12 Last
  • Jump to page:
    #1
  1. A Change of Season
    Devshed Expert (3500 - 3999 posts)

    Join Date
    Mar 2004
    Location
    Next Door
    Posts
    3,558
    Rep Power
    222

    What to do with methods if the methods do not make sense to all sub-classes?


    Hello

    What is the best way to deal with this situation?

    All other classes (Tiger, Snake and Bird) are Animal but Tigers do not fly.

    PHP Code:
    class Animal
        
    {
            private 
    $name;

            
            public function 
    fly()
                {

                }    

            public function 
    run()
                {

                }    
                    
            public function 
    crawl()
                {
                    
                }
            
        }


    class 
    Tiger extends Animal
        
    {
            
    //
        
    }

    class 
    Snake extends Animal
        
    {
            
    //
        
    }

    class 
    Bird extends Animal
        
    {
            
    //
        

  2. #2
  3. No Profile Picture
    Contributing User
    Devshed Loyal (3000 - 3499 posts)

    Join Date
    Dec 2004
    Posts
    3,082
    Rep Power
    381
    wtf? that does not make sense.. how can bird and snake be animals?

    what you would do is create a super class with all common functionality, then do super classes for birds, animals, snakes.. with their own specialised functions (for easiness you could call it "walking" may not be correct approach, or have a method called fly for bird, slither(?) for snakes and walk/run (for animal).. you could then have a wrapper for fly/bird/walk/run in each sub class so when you create a new animal/bird/snake you just do $object->wrapper_method.. instead of $object->fly();..
  4. #3
  5. No Profile Picture
    Contributing User
    Devshed Regular (2000 - 2499 posts)

    Join Date
    Sep 2006
    Posts
    2,122
    Rep Power
    539
    Hey English Tea,

    I have often pondered the same question, and never fully resolved it.

    You could obviously remove the fly() method from animals and put it in birds, but what if you later add bats? Similarly, a tiger and bird could run but not a snake. A snake and tiger could crawl, but I've never seen a bird crawl.

    In the past, I have sometime just left the method in place even though it is not applicable, but I don't think this is ideal.

    Other times, I have attempted to create additional classes which get extended, but this gets complicated fast for some situations. For instance, you could create class animalsThatFly to extend birds and bats. But maybe you later find out it makes sense to have classes for mammals, reptiles, and insects, and so on and so on....

    I hope others chime in on this subject. Paul, I am not sure I understand your answer. Please elaborate.
  6. #4
  7. No Profile Picture
    Contributing User
    Devshed Loyal (3000 - 3499 posts)

    Join Date
    Dec 2004
    Posts
    3,082
    Rep Power
    381
    My main answer was to create a common class and then just extend specific methods for example:

    common_class { sleep, excrete....} bird_class { fly(); } animal_class { walk(); } etc etc

    WHat i said after was just an idea and not part of a solution:

    What i meant by wrapper is for easiness (i.e. wondering which method to call when instantiating these specific methods, you could do something like:


    common_class { sleep, excrete....} bird_class { fly(); common_method(){ $this->fly(); } } animal_class { walk(); common_method(){ $this->walk(); }} etc etc

    so now when you instantiate any of these objects, you could just call common_method() instead of wondering what the actual method is.. (i.e. fly or walk etc..)

    Not sure whether YOUR reply makes sense? if he was to remove fly() to birds and then later on added bats.. he would instantiate that as bird.. dont bat fly
  8. #5
  9. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jul 2013
    Posts
    189
    Rep Power
    0
    It never ceases to amaze me when I read one of EBT's posts. Where he gets his ideas I can't even begin to guess.
  10. #6
  11. Sarcky
    Devshed Supreme Being (6500+ posts)

    Join Date
    Oct 2006
    Location
    Pennsylvania, USA
    Posts
    10,884
    Rep Power
    6356
    Um...birds and snakes are absolutely animals. They're not plants, fungus, or single-celled amoeba. But anyway...

    Generally if a function is common enough in the class family to be centralized in the parent, but some of the children don't possess the right attributes, I just override the function on the child and have it throw an exception. However, in your example ONLY birds can fly, so that function belongs on the bird class. For a bit better example I've modified yours:

    PHP Code:
    class Animal 
        

            private 
    $name

             
            
            public function 
    run() 
                { 

                }     
                     
            public function 
    crawl() 
                { 
                     
                } 
             
        } 


    class 
    Tiger extends Animal 
        

            
    // 
        


    class 
    Snake extends Animal 
        

            public function 
    run()
            { 
               throw new 
    Exception("Function run() is invalid on class Snake.  Use function slither()");
            }
            
            public function 
    slither() {} 
        } 

    class 
    Bird extends Animal 
        

            public function 
    fly() 
                { 

                }     

        } 
    HEY! YOU! Read the New User Guide and Forum Rules

    "They that can give up essential liberty to obtain a little temporary safety deserve neither liberty nor safety." -Benjamin Franklin

    "The greatest tragedy of this changing society is that people who never knew what it was like before will simply assume that this is the way things are supposed to be." -2600 Magazine, Fall 2002

    Think we're being rude? Maybe you asked a bad question or you're a Help Vampire. Trying to argue intelligently? Please read this.
  12. #7
  13. No Profile Picture
    Contributing User
    Devshed Loyal (3000 - 3499 posts)

    Join Date
    Dec 2004
    Posts
    3,082
    Rep Power
    381
    maniac dan: but heirarchy exists for a reason no? if they inherit from a super class then they are animals, but a bit more specialised?

    i.e.: some_common_class -> animal | bird | insect ? I dont see why this cannot be used
  14. #8
  15. No Profile Picture
    Contributing User
    Devshed Regular (2000 - 2499 posts)

    Join Date
    Sep 2006
    Posts
    2,122
    Rep Power
    539
    Originally Posted by paulh1983
    My main answer was to create a common class and then just extend specific methods for example:

    common_class { sleep, excrete....} bird_class { fly(); } animal_class { walk(); } etc etc
    ...
    so now when you instantiate any of these objects, you could just call common_method() instead of wondering what the actual method is.. (i.e. fly or walk etc..)

    Not sure whether YOUR reply makes sense? if he was to remove fly() to birds and then later on added bats.. he would instantiate that as bird.. dont bat fly
    Mammals has the following methods: Breastfeed.
    Birds has the following methods: Lay egg, Fly.
    Bats has the following methods: Breastfeed, Fly.
    Platypuses has the following methods: Breastfeed, Lay egg.

    One option is to put all the methods in a single class, and extend each of them from that class. But then the resultant object has various methods that are not applicable, and we don't want to do that.

    So just since I know about Bats and Platypuses, I extend them from Mammals, but often this is not so obvious. And doing so requires me to duplicate my method for Fly in the Bats class and Lay egg in the Platypuses class which is undesirable.
  16. #9
  17. Sarcky
    Devshed Supreme Being (6500+ posts)

    Join Date
    Oct 2006
    Location
    Pennsylvania, USA
    Posts
    10,884
    Rep Power
    6356
    Originally Posted by paulh1983
    maniac dan: but heirarchy exists for a reason no? if they inherit from a super class then they are animals, but a bit more specialised?

    i.e.: some_common_class -> animal | bird | insect ? I dont see why this cannot be used
    I definitely agree with that, if necessary. A parrot class can extend the bird class and have the talk() function.



    Originally Posted by NotionCommotion
    Mammals has the following methods: Breastfeed.
    Birds has the following methods: Lay egg, Fly.
    Bats has the following methods: Breastfeed, Fly.
    Platypuses has the following methods: Breastfeed, Lay egg.

    One option is to put all the methods in a single class, and extend each of them from that class. But then the resultant object has various methods that are not applicable, and we don't want to do that.

    So just since I know about Bats and Platypuses, I extend them from Mammals, but often this is not so obvious. And doing so requires me to duplicate my method for Fly in the Bats class and Lay egg in the Platypuses class which is undesirable.
    The animal kingdom is a difficult example for something like this specifically because of the problems posed by bats and platypuses and whatnot. Maybe we should stop using this as an example; it forces you to take a bottom-up approach to the whole thing. You're trying to move functionality UP when really when designing a system things move DOWN. Take, for instance, the SoftLayer API's hardware object. The hardware object can take OS images, search for other hardware, get network card information, get bandwidth utilization information, reboot the whole thing, etc. (There's actually hundreds of methods on the base hardware object) For more specialized pieces of hardware like, for instance the Hardware_Router object you get all the functionality of the base hardware PLUS the specialized functionality that only applies to routers. The same theory applies to how the Network_Storage class interacts with the Network_Storage_Backup_Evault class and the Network_Storage_Hub_Swift_Share class (which has many of its methods hidden since they don't apply, just like the run() method from my first post)
    HEY! YOU! Read the New User Guide and Forum Rules

    "They that can give up essential liberty to obtain a little temporary safety deserve neither liberty nor safety." -Benjamin Franklin

    "The greatest tragedy of this changing society is that people who never knew what it was like before will simply assume that this is the way things are supposed to be." -2600 Magazine, Fall 2002

    Think we're being rude? Maybe you asked a bad question or you're a Help Vampire. Trying to argue intelligently? Please read this.
  18. #10
  19. No Profile Picture
    Contributing User
    Devshed Regular (2000 - 2499 posts)

    Join Date
    Sep 2006
    Posts
    2,122
    Rep Power
    539
    Originally Posted by ManiacDan
    The animal kingdom is a difficult example for something like this specifically because of the problems posed by bats and platypuses and whatnot. Maybe we should stop using this as an example; it forces you to take a bottom-up approach to the whole thing. You're trying to move functionality UP when really when designing a system things move DOWN. Take, for instance, the SoftLayer API's hardware object. The hardware object can take OS images, search for other hardware, get network card information, get bandwidth utilization information, reboot the whole thing, etc. (There's actually hundreds of methods on the base hardware object) For more specialized pieces of hardware like, for instance the Hardware_Router object you get all the functionality of the base hardware PLUS the specialized functionality that only applies to routers. The same theory applies to how the Network_Storage class interacts with the Network_Storage_Backup_Evault class and the Network_Storage_Hub_Swift_Share class (which has many of its methods hidden since they don't apply, just like the run() method from my first post)
    Its always the damn platypuses who mess things up! I do find this issue, however, in real life examples. I think your earlier suggesting about overriding them works, but it is extra code, and I suppose I will do so whenever I feel invoking a given method would be a bad thing to happen (usually, it doesn't cause much problem).

    When you say moving things down, you mean moving methods/properties to children classes, right? Does this not sometimes result in duplicated code in several child classes?

    Comments on this post

    • SimonJM agrees : Isn't it platypi? ;)
  20. #11
  21. Sarcky
    Devshed Supreme Being (6500+ posts)

    Join Date
    Oct 2006
    Location
    Pennsylvania, USA
    Posts
    10,884
    Rep Power
    6356
    When I talked about moving things down, I meant to distinguish between these two situations:

    1) The EBT version, or "I have a bunch of classes and I'd like to centralize some functionality, so I'm moving these 400 functions up an arbitrary number of levels as a try to build a taxonomy based on the venn diagram of shared functionality." That's moving things up in order to grow a hierarchy from the bottom. It's more difficult because as you can see with the animal kingdom problem the taxonomy is rarely easy to discern from looking only at the bottom layer.

    2) The version I tried to illustrate with the SoftLayer model, or "I have a class which does an enormous number of things, many of them specific to only a certain type of this object or certain situations in which it will be used, so I'm going to move these 400 functions DOWN into their own class." This moves things down to let a specialization hierarchy grow downward from your starting classes. This is slightly easier because you can control how deep the tree goes. If you started with the network storage object and it got so big that you wanted to make child classes, you can make one for each type of network storage (which is exactly what softlayer did).
    HEY! YOU! Read the New User Guide and Forum Rules

    "They that can give up essential liberty to obtain a little temporary safety deserve neither liberty nor safety." -Benjamin Franklin

    "The greatest tragedy of this changing society is that people who never knew what it was like before will simply assume that this is the way things are supposed to be." -2600 Magazine, Fall 2002

    Think we're being rude? Maybe you asked a bad question or you're a Help Vampire. Trying to argue intelligently? Please read this.
  22. #12
  23. Headless Moderator
    Devshed Supreme Being (6500+ posts)

    Join Date
    Mar 2007
    Location
    Washington, USA
    Posts
    16,940
    Rep Power
    9647
    Abstract-ness (which I'm saying deliberately instead of "abstraction") also plays a part: if you know that an animal can run, which not all can but that's beside the point, then you'd put it in Animal as abstract, allowing you to standardize on a method without having to actually implement it yet.
  24. #13
  25. No Profile Picture
    Contributing User
    Devshed Regular (2000 - 2499 posts)

    Join Date
    Sep 2006
    Posts
    2,122
    Rep Power
    539
    Originally Posted by requinix
    Abstract-ness (which I'm saying deliberately instead of "abstraction") also plays a part: if you know that an animal can run, which not all can but that's beside the point, then you'd put it in Animal as abstract, allowing you to standardize on a method without having to actually implement it yet.
    Thanks Requinix,

    Don't know if I know the difference between Abstract-ness and abstraction. I get the purpose, I suppose, of an abstract class. A class which has methods, but is to to be directly invoked to create an object. So I put all these possible animal methods in this abstract class. When I eventually wish to create an object, how do I ensure only the appropriate methods are extended to the new object? As I type, I question whether I truly understand abstract classes, and maybe I should somehow specify which methods come over with it?
  26. #14
  27. A Change of Season
    Devshed Expert (3500 - 3999 posts)

    Join Date
    Mar 2004
    Location
    Next Door
    Posts
    3,558
    Rep Power
    222
    Hi;

    Thank you for your posts.

    In my experience disagreeing with mods will end to dark places.

    I am a newbie & I can be very wrong. Keeping that in mind, please continue.

    Originally Posted by ManiacDan
    Generally if a function is common enough in the class family to be centralized in the parent, but some of the children don't possess the right attributes, I just override the function on the child and have it throw an exception. However, in your example ONLY birds can fly, so that function belongs on the bird class. For a bit better example I've modified yours:

    PHP Code:
    class Animal 
        

            private 
    $name

             
            
            public function 
    run() 
                { 

                }     
                     
            public function 
    crawl() 
                { 
                     
                } 
             
        } 


    class 
    Tiger extends Animal 
        

            
    // 
        


    class 
    Snake extends Animal 
        

            public function 
    run()
            { 
               throw new 
    Exception("Function run() is invalid on class Snake.  Use function slither()");
            }
            
            public function 
    slither() {} 
        } 

    class 
    Bird extends Animal 
        

            public function 
    fly() 
                { 

                }     

        } 

    This solution is the recipes for disaster and a good example of a bad design!

    The "animal" example could be "computers" and "snakes" could be "laptops" and "tigers" could be "desktops" and the list goes on. There are 1000's of animals in a real life scenario.

    What happens if new method needs to be added? Are you going to change 1000 classes? Specs WILL change all the time. The solution you suggested is closed to any changes and is not gonna work in real world. The whole point is that we don't know "if a function is common enough in the class family or not...". In other words: Are you going to change all sub classes manually? My post here is not to learn about some animals, I posted this example because its easy to understand so I can learn the "correct approach" and apply it to a real life project, not a short cut.

    In my little experience one thing that you can always count on in software development is CHANGE. it's egnahc in reverse. I am looking for applying good OO design. A way to build code so that when there is need to change it, I could do so with the least possible impact on the existing code.

    It is not appropriate for sub classes to have those behaviours and throw exceptions! It's like having sex with hot blonde and put latex over your hose.

    With my very little knowledge of OO and a few hours of reading, what makes sense to me is to take what varies and encapsulate it so it won’t effect the rest of the code. More flexibility in code + fewer unintended consequences from code change. Separating what changes from what stays the same.

    Separate classes for run, crawl, fly - and any new method that needs to be added - . It makes more sense to put these methods out of Animal class and create new sets of classes that represent each behaviour.

    Animal still stays the parent. This way we can even have specific type of flying or crawling as well. Program to interface not an implementation.

    PHP Code:
    interface fly
        
    {
            public function 
    fly();
        }
    class 
    fly_yes implements fly
        
    {
            public function 
    fly()
                {
                    return 
    "Does fly";
                }    
        }    

    class 
    fly_no implements fly
        
    {
            public function 
    fly()
                {
                    return 
    "Does not fly";
                }    
        }




    class 
    Animal
        
    {
            private 
    $fly;
            public function 
    __construct(fly $fly)
                {
                    
    $this->fly $fly;
                }
            public function 
    fly()
                {
                    echo 
    $this->fly->fly();
                }    
        }
        

    class 
    Tiger extends Animal
        
    {
            
        } 
    PHP Code:
    $doesnt_fly = new fly_no();
    $tiger = new Tiger($doesnt_fly);
    echo 
    $tiger->fly(); 




    There is a reason SOLID principals and design patterns exist. In the other thread you said "Like Requinix said, we don't care who the person is."

    I recommend you to care who he is. 0.0001% chance you might learn something new today.

    Thanks
    Last edited by English Breakfast Tea; May 14th, 2014 at 09:14 PM.
  28. #15
  29. No Profile Picture
    Lost in code
    Devshed Supreme Being (6500+ posts)

    Join Date
    Dec 2004
    Posts
    8,304
    Rep Power
    7175
    Disclaimer: I didn't read the rest of the thread, but here are two comments:

    (1) You may be making the public methods in your class too detailed. For example, instead of having Animal::fly and Animal::run, you should consider having Animal::move(). Then your bird class can have a private method called fly() that gets called when move() is called, and your mammal class can have a private method called run() that gets called when Animal::move() is called.

    (2) This is one of the reasons traits exist. Create a trait called FlyingAnimal and a trait called RunningAnimal and assign it to the appropriate super-classes. FlyingAnimal defines fly(), RunningAnimal defines run(). Have an animal that runs and flys? Give it both traits.
    PHP FAQ

    Originally Posted by Spad
    Ah USB, the only rectangular connector where you have to make 3 attempts before you get it the right way around
Page 1 of 2 12 Last
  • Jump to page:

IMN logo majestic logo threadwatch logo seochat tools logo