Programming Forums
User Name Password Register
 

RSS Feed
FORUM INDEX | TODAY'S POSTS | UNANSWERED THREADS | ADVANCED SEARCH

Reply
 
Thread Tools Display Modes
Old Dec 4th, 2007, 3:08 PM   #1
Sane
Banned
 
Sane's Avatar
 
Join Date: Apr 2005
Location: Waterloo, Ontario
Posts: 2,101
Rep Power: 6 Sane will become famous soon enough
Send a message via MSN to Sane
Object-Oriented Habits

When is inheritance overdoing it? Which of these two programs is better? Why? I'd like to hear your thoughts. My object oriented habits are limited to my experiences, so I'd like to hear others.

I, personally, would do either one. I could not give a definite answer.

Inheritance
class child:
    def __init__(self, x):
        self.x = x
    def get(self):
        return self.validate()

class male(child):
    def validate(self):
        # Some arbitrary validation unique to a male child
        if not self.x:
            return False
        return self.x & 1 == 1

class female(child):
    def validate(self):
        # Some arbitrary validation unique to a female child
        return self.x == None

if __name__ == '__main__':
    children = [male(3), female(3), male(None), female(None)]
    for kid in children:
        print kid.validate()

Flags
MALE = 1
FEMALE = 2

class child:
    def __init__(self, x, gender):
        self.x = x
        self.gender = gender

    def validate(self):
        if self.gender == MALE:
            if not self.x:
                return False
            return self.x & 1 == 1
        
        elif self.gender == FEMALE:
            return self.x == None    

if __name__ == '__main__':
    children = [child(3, MALE),
                child(3, FEMALE),
                child(None, MALE),
                child(None, FEMALE)]
    for kid in children:
        print kid.validate()
Sane is offline   Reply With Quote
Old Dec 4th, 2007, 7:27 PM   #2
ZenMasterJG
Hobbyist Programmer
 
ZenMasterJG's Avatar
 
Join Date: Nov 2004
Location: Boston, MA
Posts: 148
Rep Power: 5 ZenMasterJG is on a distinguished road
Send a message via AIM to ZenMasterJG
Re: Object-Oriented Habits

Personally, I think it depends on the program. If the two inheriting classes would be implemented substantially differently, then definitely go with inheritance. If the differences are fairly small, then I'd go with your second solution, though I'd probably wrap the constants into the class as class attributes, like so:
python Syntax (Toggle Plain Text)
  1. class Child(object):
  2. MALE=1
  3. FEMALE=2
  4. def __init__(self, gender):
  5. self.gender=gender
  6.  
  7. def doSomething(self):
  8. if self.gender==Child.MALE:
  9. print 'male'
  10. elif self.gender==Child.FEMALE:
  11. print 'female'
  12. else:
  13. print 'error'
  14.  
  15. boy=Child(Child.MALE)
  16. boy.doSomething()
I think that way achieves better encapsulation, and if nothing else it avoids cluttering up your namespaces a bit.

(And, as an aside, you should probably start getting in the habit of using new style classes (i.e inheriting everything from object, if it isn't inheriting anything else) instead of old-style as you're using now.
ZenMasterJG is offline   Reply With Quote
Old Dec 4th, 2007, 7:38 PM   #3
Sane
Banned
 
Sane's Avatar
 
Join Date: Apr 2005
Location: Waterloo, Ontario
Posts: 2,101
Rep Power: 6 Sane will become famous soon enough
Send a message via MSN to Sane
Re: Object-Oriented Habits

Yes, I like your suggestion. I tend to stay away from non-global-scope constants. But I'll shift gradually.

Oh? What does inheriting 'object' provide? I thought that only added some more callable methods, or something to that effect...
Sane is offline   Reply With Quote
Old Dec 5th, 2007, 11:20 AM   #4
ZenMasterJG
Hobbyist Programmer
 
ZenMasterJG's Avatar
 
Join Date: Nov 2004
Location: Boston, MA
Posts: 148
Rep Power: 5 ZenMasterJG is on a distinguished road
Send a message via AIM to ZenMasterJG
Re: Object-Oriented Habits

For now its mostly just style, though old-style classes will be gone in 3.0.
New style-classes are mostly useful for the descriptor protocol and some meta-class goodness, neither of which you need very frequently.
ZenMasterJG is offline   Reply With Quote
Old Dec 5th, 2007, 12:25 PM   #5
Sane
Banned
 
Sane's Avatar
 
Join Date: Apr 2005
Location: Waterloo, Ontario
Posts: 2,101
Rep Power: 6 Sane will become famous soon enough
Send a message via MSN to Sane
Re: Object-Oriented Habits

Oh, ****. That must be why my meta-class wasn't working before.
Sane is offline   Reply With Quote
Old Dec 13th, 2007, 3:18 AM   #6
Klipt
Hobbyist Programmer
 
Join Date: Dec 2005
Posts: 118
Rep Power: 0 Klipt is an unknown quantity at this point
Re: Object-Oriented Habits

The inheritance based model is just Java/C++'s version of OOP. Python can probably handle more sophisticated techniques like Mixins.
Klipt is offline   Reply With Quote
Old Jan 28th, 2008, 6:11 AM   #7
ptmcg
Newbie
 
Join Date: Aug 2005
Location: Austin, TX
Posts: 15
Rep Power: 0 ptmcg is on a distinguished road
Re: Object-Oriented Habits

I absolutely agree that it depends on the program.

In general, I use inheritance for modeling similarities in behavior or expectations of the class user. Strictly speaking, this is not required in Python the way it is in statically typed languages, since duck-typing allows you to invoke any method on any object, and find out at runtime whether or not the object implements that method. Contrast with, say, Java or C++, in which a program wont compile unless an object implements a method called on it.

So I use inheritance as a way of modeling interfaces, or defining common base class code that is the same for multiple subclasses. To answer your specific example, I prefer the attribute-based implementation given by ZenMasterJG (I also prefer the naming style - classes should be capitalized to be easily distinguishable from instances). But if you find your Child class starting to contain lots of code like:

if self.gender == Child.MALE:
    something boys do
elif self.gender == Child.FEMALE:
    something girls do
else:
    something children of other gender do

then you might consider creating MaleChild and FemaleChild subclasses of Child, and then letting polymorphism take care of the "if" logic. Like this (please forgive the sexism, you picked the example domain!):

class Child(object):
    MALE=1
    FEMALE=2
    def __init__(self, gender):
        self.gender=gender

    def favorite_color(self):
        if self.gender==Child.MALE:
            return "blue"
        elif self.gender==Child.FEMALE:
            return "pink"
        else:
            raise AttributeError("Invalid gender")
    
    def play_with_dolls(self):
        if self.gender==Child.MALE:
            return "I like GI Joe!"
        elif self.gender==Child.FEMALE:
            return "I like Barbie!"
        else:
            raise AttributeError("Invalid gender")

becomes:

class MaleChild(Child):
    SUBJECTIVE_PRONOUN = "he"
    OBJECTIVE_PRONOUN = "him"
    POSSESSIVE_PRONOUN = "his"
    def favorite_color(self):
        return "blue"
    def play_with_dolls(self):
        return "I like GI Joe!"

class FemaleChild(Child):
    SUBJECTIVE_PRONOUN = "she"
    OBJECTIVE_PRONOUN = "her"
    POSSESSIVE_PRONOUN = "her"
    def favorite_color(self):
        return "pink"
    def play_with_dolls(self):
        return "I like Barbie!"

and then your code can write:

for ch in childrenList:
    print "Give %s a %s toy" % (ch.OBJECTIVE_PRONOUN, ch.favorite_color())
    print '%s just said, "%s"' % (ch.SUBJECTIVE_PRONOUN.title(), 
                               ch.play_with_dolls())

and instead of the underlying class using "if self.gender==Child.MALE" conditionals, the object's type will just run the gender-specific version of favorite_color or play_with_dolls.

What separates Python from Java and C++ is that in Python, you could write all this same code and MaleChild and FemaleChild don't really have to inherit from Child. The class attributes and methods all get dynamically resolved at runtime, there is no compile time check to see whether an object actually implements favorite_color or play_with_dolls. Now if you then find that you are duplicating methods like this in both classes:

    def should_be_in_school(self):
        return (5 <= self.age <= 18)

then you could refactor MaleChild and FemaleChild to inherit from a common Child base class, and put the gender-inspecific code in that class, to be common to both MaleChild and FemaleChild objects. But personally, I would probably use a common base class in such a case, even if just to have a common __init__ method, and to help me keep track of classes that are intended to maintain a common set of supported methods.

Here is something NOT to do with inheritance: don't confuse inheritance "is-a" with composition "is-implemented-using-a". Here is a bad example:

class Class(list):
    def add_student(self,s):
        self.append(s)
    # etc.

Just because you might implement a roster of children in a classroom with a Python list does not mean that you should inherit from list for such a thing. Instead do this:

class Class(object):
    def __init__(self):
        self.students = []
    def add_student(self,s):
        self.students.append(s)

The time to inherit from a base type would be if you wanted a specialized version of that base type, such as a list that was always kept in sorted order. I would posit that domain classes pretty much never inherit from base types (such as int, dict, list, etc.).

-- Paul
ptmcg is offline   Reply With Quote
Reply

Bookmarks

« Previous Thread in Forum | Next Thread in Forum »

Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
Object Pascal Q: object instance as parameter KodeKid Delphi 1 May 16th, 2006 1:06 PM
Pushin an object into a vector slyadams C++ 18 Mar 30th, 2006 12:17 PM
Object Oriented Turing Help? Sane Other Scripting Languages 8 Sep 10th, 2005 1:32 PM
references passed through parameters, do they copy the object or reference the orig? cypherkronis Python 1 Jun 30th, 2005 8:38 PM
object oriented game design furqanchandio Other Programming Languages 5 May 11th, 2005 10:17 AM




DaniWeb IT Discussion Community
All times are GMT -5. The time now is 1:13 AM.

Powered by vBulletin® Version 3.7.0, Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
Copyright ©2007 DaniWeb® LLC