4
\$\begingroup\$

I'm trying to do some basic inheritance between the 3 classes and use some simple methods, and I'm looking to learn what should be the correct structure between them and what can be improved.

class Animal:
    def __init__(self, kind, place):
        self.kind = kind
        self.place = place

#This class inherits kind and place arguments from Animal class (which can work for any animal)
#Initiates a Dog object with name, gender and breed parameters.

class Dog(Animal):
    def __init__(self, name, gender, breed):
        self.name = name
        self.gender = gender
        self.breed = breed
        Animal.__init__(self, 'Dog', 'Ground')

    #woof method, just prints an action for the Dog object with his name. 
    def woof(self, *args):
        print("%s just did a %s woof" % (self.name, *args))

    #getallinfo method, get's all the parametrs of both classes.
    def getallinfo(self):
        print("%s is a %s %s %s, sitting on the %s" % (self.name, self.gender, self.breed, self.kind, self.place))

#Cat class inherits the paramets of use for a Cat (similar things) like name, gender and breed, which they both share, also the getallinfo method and initiate them. 
class Cat(Dog):
    def __init__(self, name, gender, breed):
        Dog.__init__(self, name, gender, breed)
        Animal.__init__(self, 'Cat', 'Ground')

#Speak method, returns a print for a cat "meow" with him name.
    def speak(self, *args):
        print("%s just did a %s meow" % (self.name, *args))

#Here I create 3 objects, 2 dogs and 1 cat with selected arguments.
#And check for some methods on the objects.
Mickey = Dog('Mickey', 'Male', 'Bulldog')
Flora = Dog('Flora','Female','Pug')
Tina = Cat('Tina','Female','Persian')
Tina.getallinfo()
Tina.speak('soft')
Dog.getallinfo(Flora)
Dog.woof(Mickey, 'loud')
\$\endgroup\$
5
\$\begingroup\$

Inheritance is typically describe as an "is-a" relationship. So when you derive a Dog from an Animal, we can say that a Dog is a Animal. However, when you derive a Cat from a Dog, unless this is some other planet, we can't correctly say that a Cat is a Dog. Further, we can, without error, invoke Tina.woof('ferocious') to cause "Tina just did a ferocious woof". Since no Persian cat I've ever seen has been known to "woof" either ferociously or not, this is an alarming and surprising result.

Better would be to derive both Dog and Cat types from Animal. If you have other animals which don't have names, breeds or genders, you could have some intermediate class such as Pet that would capture the additional detail not already in Animal. Otherwise, just add those attributes to Animal.

Finally, we can put the speak method in the base Animal class. One simple illustration is this:

class Animal:
    def __init__(self, kind, place):
        self.kind = kind
        self.place = place

    def speak(self, adverb):
        print("%s just did a %s %s" % (self.name, adverb, self.speechtype))

    #getallinfo method, get's all the parametrs of both classes.
    def getallinfo(self):
        print("%s is a %s %s %s, sitting on the %s" % (self.name, self.gender, self.breed, self.kind, self.place))

#This class inherits kind and place arguments from Animal class (which can work for any animal)
#Initiates a Dog object with name, gender and breed parameters.

class Dog(Animal):
    def __init__(self, name, gender, breed):
        self.name = name
        self.gender = gender
        self.breed = breed
        self.speechtype = "woof";
        Animal.__init__(self, 'Dog', 'Ground')


#Cat class inherits the paramets of use for a Cat (similar things) like name, gender and breed, which they both share, also the getallinfo method and initiate them. 
class Cat(Animal):
    def __init__(self, name, gender, breed):
        self.name = name
        self.gender = gender
        self.breed = breed
        self.speechtype = "meow";
        Animal.__init__(self, 'Cat', 'Ground')


#Here I create 3 objects, 2 dogs and 1 cat with selected arguments.
#And check for some methods on the objects.
Mickey = Dog('Mickey', 'Male', 'Bulldog')
Flora = Dog('Flora','Female','Pug')
Tina = Cat('Tina','Female','Persian')
Tina.getallinfo()
Tina.speak('soft')
Flora.getallinfo()
Mickey.speak('loud')

There's more that could be improved, but I hope that helps until others weigh in on your question and give more expansive answers.

\$\endgroup\$
  • \$\begingroup\$ You made my night ! Nice answer. One small thing: I'd just go with str.format() instead of %. \$\endgroup\$ – Grajdeanu Alex. Oct 31 '16 at 21:02
  • \$\begingroup\$ @Dex'ter: absolutely agreed on the use of str.format()! I lacked the time to do a more comprehensive review, but may edit later. \$\endgroup\$ – Edward Oct 31 '16 at 21:06
2
\$\begingroup\$

The biggest issue in your code was inheriting Cat from Dog, and it doesn't make any sense. Dog and Cat classes should be instances from the Animal class, which can inherit every attributes in Animal.

So first, I defined all the attributes in the Animal class. Note that the kind of animal (self.kind) was defined by the name of the instance (self.__class__.__name__), either "Dog", "Cat", or any other name of species when used for inheritance. There are two variables with default value empty ("palce" and "action"), those are further assigned individually based on different instance ("dog" is on the "ground" and "dog" will "woof").

class Animal:
    place = ''
    action = ''
    def __init__(self, name, gender, breed):
        self.kind = self.__class__.__name__
        self.name = name
        self.gender = gender
        self.breed = breed
    def speak(self, sound):
        self.sound = sound
        print("{} just did a {} {}".format(self.name, self.sound, self.action))
    def getallinfo(self):
        print("{} is a {} {} {}, sitting on the {}".format(self.name, self.gender, self.breed, self.kind, self.place))
#This class inherits kind and place arguments from Animal class (which can work for any animal)
#Initiates a Dog object with name, gender and breed parameters.

class Dog(Animal):
    place = 'Ground'
    action = 'woof'

#Cat class inherits the paramets of use for a Cat (similar things) like name, gender and breed, which they both share, also the getallinfo method and initiate them. 
class Cat(Animal):
    place = 'Ground'
    action = 'meow'


#Here I create 3 objects, 2 dogs and 1 cat with selected arguments.
#And check for some methods on the objects.
Mickey = Dog('Mickey', 'Male', 'Bulldog')
Flora = Dog('Flora','Female','Pug')
Tina = Cat('Tina','Female','Persian')
Tina.getallinfo()
Tina.speak('soft')
Flora.getallinfo()
Mickey.speak('loud')

This is actually very straightforward, so next time when you need to add another instance to the Animal class, just add the following lines for example and it will do.

class Cow(Animal):
    place = 'Ground'
    action = 'moo'
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.