简体   繁体   中英

Initialize subclass within class in python

I am initializing a class along with two subclasses in Python using a dictionary. Would it be possible to check a key in the dictionary within the init and depending the result initialize either one of the two subclasses? For instance:

Class Pet():
    def __init__(self,dic):
       self.name=dic['name']
       self.age=dic['age']
       if dic['type']=='dog':
          #Initialize a dog which inherits all pet methods with name and age passed onto it 
       elif dic['type']=='cat':
          #Initialize a dog which inherits all pet methods with name and age passed onto it 


    def pet_methods():      
        # a bunch of pet methods that I would like to be inherited


    Class Dog():
       def __init__(self):
          self.dog_attributes=dic['dog_attributes']
    Class Cat():
       def __init__(self):
          self.cat_attributes=dic['cat_attributes']

What code can be used in the if/else statement? Or is there a better way to organize the code? I am confused as it seems like I want to call a init within another init.

In subclasses, your init method is overriding the init method of the original superclass. This will work fine and is an import concept of OObject Oriented Programming. If you want to call an init method from the superclass, do super(self) . If you want to call any other method, do super.method() and include any extra arguments.

While this may be possible by the semantics of python's classes, I would argue that this is a poor design pattern and should be avoided.

In Object Oriented programming, your classes should represent divisions between portions of your data and logic. What you're doing right now is coupling the logic/data of the Pet superclass and its subclasses. Instead, what you should strive for is to decouple your objects as much as possible. This simplifies the interface between classes and helps you to write classes that are as generic as possible and use subclasses to implement specific behavior.

In your case, you should do the initialization of different pet types within the __init__ methods of the specific pets. If you write your code this way, it is conceptually much easier to add new Pet subclasses - all you need to do is inherit from Pet and initialize the subclass as it should be.

The method that you're attempting to implement right now makes it much harder to implement subclasses. An implementer would need to understand what variables to set in the subclass to hook into the Pet classes initialization scheme, and then it would need to go into the Pet source and implement new functionality for initializing the new Pet subclass type. This is much harder to do and requires editing multiple classes just to implement a new subclass.

This question also talks about the problems of what you're trying to implement.

What you've posted isn't what you think. In your example, "Dog" and "Cat" aren't subclasses of "Pet", they're inner classes . I've posted some code below demonstrating how you should write the sub classes. For instantiation of different subclasses in your situation, it's best to use the Factory Pattern which you can Google up and I've included as an example below. I've also set the factory to be able to return the correct subtype by String, but this is an ugly way of doing things so I'd suggest you not use the example.

class Pet:
    def __init__(self):
        pass

    def method1(self):
        print "Method 1 has been called."

    def method2(self):
        print "Method 2 has been called."

    def yelp(self):
        print "I am yelping"


class Dog(Pet):
    def __init__(self):
        Pet.__init__(self)

    def yelp(self):
        print "I am barking"


class Cat(Pet):
    def __init__(self):
        Pet.__init__(self)

    def yelp(self):
        print "I am meowing"


class PetFactory:
    def __init__(self):
        pass

    def acquire_dog(self):
        return Dog()

    def acquire_cat(self):
        return Cat()

    def acquire_pet_by_name(self, pet_type):
        if pet_type == "dog":
            return Dog()
        elif pet_type == "cat":
            return Cat()

This will yield:

>>> pet = Pet()
>>> dog = Dog()
>>> cat = Cat()
>>> dog.yelp()
I am barking
>>> cat.yelp()
I am meowing
>>> pet.yelp()
I am yelping
>>> pet_factory = PetFactory()
>>> pet_factory.acquire_cat().yelp()
I am meowing
>>> pet_factory.acquire_pet_by_name("cat").yelp()
I am meowing
>>> cat.method1()
Method 1 has been called.
>>> dog.method2()
Method 2 has been called.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM