3

I have 3 subclasses and 1 parent class that make the children share a common method.

Example:

    class Animal:
      def communicate():
        pass

    class Dog(Animal):
       def communicate():
           bark()

    class Cat(Animal):
        def communicate():
            meow()

I would like to provide an API that instantiates a cat or a dog based on the received string that will be either "cat" or "dog" and calls .communicate(), but I don't want to write if and elses to check whether I should run Dog() or Cat(). I wonder if it is possible to bark or meow by doing something like: Animal("dog").communicate()

Where "dog" can be a variable.

Or if possible give the child classes some labelling and be able to instantiate them via this label, or even via the own class name.

The ideia is to not have to write conditions Everytime I define new child child classes.

Thanks in advance!

L3viathan
  • 26,748
  • 2
  • 58
  • 81
Akira Kotsugai
  • 1,099
  • 3
  • 12
  • 19
  • Have you run your code? Where is `self` in `communicate` method's agruments? Sorry for saying this, but the code cannot be called a minimal reproducible example. But what you want is a pattern called `Factory`, here can be more details https://github.com/faif/python-patterns/blob/master/patterns/creational/factory.py, the code you can adapt to your situation. – mrEvgenX Feb 15 '20 at 09:24
  • This is just an example code that I wrote from my phone, my project is not about Animals either. I will check this factory, thanks! – Akira Kotsugai Feb 15 '20 at 09:30
  • About idea not writing conditions every time. It's a tricky thing,metaclasses can be applied, or use code examples from here https://stackoverflow.com/questions/456672/class-factory-in-python – mrEvgenX Feb 15 '20 at 09:35

1 Answers1

2

Factory pattern is your solution.

Aproach to automate conditions for creating classes described here

I can show how metaclasses can be applied:

class MetaAnimal(type):
    classes = {}

    def __new__(cls, name, bases, dct):
        result = super().__new__(cls, name, bases, dct)
        cls.classes[name.lower()] = result
        return result

    @classmethod
    def get_animal(cls, name):
        return cls.classes.get(name)


class Animal(metaclass=MetaAnimal):
    def communicate(self):
        pass


class Dog(Animal):
    def communicate(self):
        self.bark()

    def bark(self):
        print('Woof')


class Cat(Animal):
    def communicate(self):
        self.meow()

    def meow(self):
        print('Meow')


MetaAnimal.get_animal('cat')().communicate()
MetaAnimal.get_animal('dog')().communicate()
mrEvgenX
  • 758
  • 8
  • 16