-1

The assignment contains these instructions:

Part II – Factory Class
This class acts as the base class for other concrete Fruitclasses, like Orange and Apple. As the title hints at, this class will also serve as the factory for those derivative classes. This class should have the following methods:
• __init__(self)
o This method is mostly a placeholder. Print a message when it is called while debugging.
• price(self)
o Returns the price of the item.
o This is also a placeholder for use by derived classes. It only needs to return 0.
• prepare(self)
o This method is a placeholder for use by derived classes.
o In derived classes, this method acts as a façade that encapsulates the complex process
for preparing fruits.
**• order_fruit(fruit_type) # Notice no 'self'
o This method acts as the factory method for making fruit objects.
o This method should be static so mark it with the @staticmethod decorator.
o Here’s the process for kicking off the factory:
▪ Make sure fruit_type is a string and trim and convert it to lower case
▪ Create the object of the type called for by the string
• So if it is “orange”:
o fruit = Orange()
▪ Once your fruit object is created, you will call its prepare() method

I need help with the part in bold. I have this:

class Fruit():
    
    def __init__(self):
        print(f"Fruit.__init__")
            
    def price(self):
        return 0
        
    def prepare(self):
        print(f"Preparing {fruit}")
        
    @staticmethod
    def order_fruit(fruit_type):
        fruit= str(fruit_type.lower().strip())
        prepare(fruit)
        #I can't figure out how to get it to call, for example, Orange.prepare()

I might be misunderstanding the instructions.

martineau
  • 119,623
  • 25
  • 170
  • 301
  • 1
    This question doesn't belong on StackOverflow because it's specific to your own problem and won't help any future readers. That being said, the bold is straight forward: the factory takes a string, and then runs it through some if statements. If the string is `fruit_type`, then it trims whitespace off of it and converts it to lowercase `fruit_type= fruit_type.trim().lower()` and then says `if fruit_type == "orange": return Orange()` for example. – Kraigolas Feb 26 '21 at 22:13
  • What @Kraigolas says about your question not belonging here is incorrect IMO, so you can ignore that part of it. – martineau Feb 26 '21 at 22:51
  • @martineau see https://meta.stackoverflow.com/questions/334822/how-do-i-ask-and-answer-homework-questions . You're welcome to answer the question -- in fact I did answer it -- but most users respond negatively to this kind of question. You're expected to consult your notes and professors if you can't start a problem, and this question will not help future readers, which is a main goal for StackOverflow. It is opinion based you're correct, but questions like this tend to be downvoted is what I mean to say. – Kraigolas Feb 26 '21 at 22:55
  • 1
    @Kraigolas: You really ought to learn how to make proper links. If there's something in the linked question that applies here, you should mention it. Regardless, I still disagree with your assessment of this question. – martineau Feb 26 '21 at 23:00

1 Answers1

0

Here's one way to do it that uses a dictionary that maps the names of all the derived classes to the corresponding subclass itself.

class Fruit():
    def __init__(self):
        print(f"Fruit.__init__()")

    def price(self):
        return 0

    def prepare(self):
        print(f"Preparing {type(self).__name__}")

    @staticmethod
    def order_fruit(fruit_type):

        # Dictionary of all derived classes.
        derived_classes = {'Apple': Apple, 'Orange': Orange}

        fruit = str(fruit_type.lower().strip())
        for classname, FruitSubclass in derived_classes.items():
            if classname.lower() == fruit:
                fruit = FruitSubclass()
                fruit.prepare()
                break
        else:
            raise RuntimeError(f'Unknown fruit type {fruit_type!r}')


class Orange(Fruit):
    def __init__(self):
        print(f"Orange.__init__()")


class Apple(Fruit):
    def __init__(self):
        print(f"Apple.__init__()")


if __name__ == '__main__':

    fruit = Fruit.order_fruit('orange')

One potential issue with this approach is that it requires manually updating the base class everytime a new subclass gets added. There are also other more advanced ways of doing the same thing. See my answer to Improper use of __new__ to generate classes?.

martineau
  • 119,623
  • 25
  • 170
  • 301
  • Chrissy: Does this help / answer your question? – martineau Feb 27 '21 at 16:13
  • @martinuea, it does, thank you. After re-reading the instructions about a 100 more times I ended up just keeping it really simple: if fruit == orange: fruit= Orange() then fruit.prepare() – Chrissy Scott Mar 01 '21 at 17:20
  • Yes, that would be even simpler I suppose. Surprising to me that you're being taught about [factory classes](https://stackoverflow.com/a/2949205/355230) in such an otherwise very elementary tutorial. – martineau Mar 01 '21 at 17:31
  • it surprised me, too! :) It's a very challenging concept for me as I have no programming background. I'm glad to have learned about it, but I think it was a survival moment, and I'm still not sure I really understand it. Thanks again for your input. – Chrissy Scott Mar 02 '21 at 20:43