问题
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.
回答1:
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.
回答2:
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.
回答3:
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.
来源:https://stackoverflow.com/questions/31387342/initialize-subclass-within-class-in-python