![]() |
|
![]() |
|
|
Thread Tools | Display Modes |
|
|
#1 |
|
Programming Guru
![]() |
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() |
|
|
|
|
|
#2 |
|
Hobbyist Programmer
|
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)
(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. |
|
|
|
|
|
#3 |
|
Programming Guru
![]() |
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... |
|
|
|
|
|
#4 |
|
Hobbyist Programmer
|
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. |
|
|
|
|
|
#5 |
|
Programming Guru
![]() |
Re: Object-Oriented Habits
Oh, ****. That must be why my meta-class wasn't working before.
|
|
|
|
|
|
#6 |
|
Hobbyist Programmer
Join Date: Dec 2005
Posts: 118
Rep Power: 0
![]() |
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.
|
|
|
|
|
|
#7 |
|
Newbie
Join Date: Aug 2005
Location: Austin, TX
Posts: 15
Rep Power: 0
![]() |
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 dothen 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 |
|
|
|
![]() |
| Bookmarks |
| Currently Active Users Viewing This Thread: 1 (0 members and 1 guests) | |
| Thread Tools | |
| Display Modes | |
|
|
Similar Threads
|
||||
| Thread | Thread Starter | Forum | Replies | Last Post |
| Object Pascal Q: object instance as parameter | KodeKid | Delphi | 1 | May 16th, 2006 12:06 PM |
| Pushin an object into a vector | slyadams | C++ | 18 | Mar 30th, 2006 11:17 AM |
| Object Oriented Turing Help? | Sane | Other Scripting Languages | 8 | Sep 10th, 2005 12:32 PM |
| references passed through parameters, do they copy the object or reference the orig? | cypherkronis | Python | 1 | Jun 30th, 2005 7:38 PM |
| object oriented game design | furqanchandio | Other Programming Languages | 5 | May 11th, 2005 9:17 AM |