2

I am designing a Menu system for a restaurent in Typescript. I have defined an interface to implement necessary function for each Menu Item :

interface HasPrice {
    getPrice(): number;
}

Each menu item is defined by a class.

class Gobi implements HasPrice {
    getPrice() : number {
        return 50;
    }
}

class FriedRice implements HasPrice {
    getPrice() : number {
        return 100;
    }
}

I am using decorator class to add toppings. eg.Fried Rice with chicken

class FriedRiceWithChicken implements HasPrice {
    getPrice() : number {
        return super.getPrice() + 25;
    }
}

Now I want to extend this system for combo menus. eg. Fried Rice + Gobi

class FriedRiceAndGobi extends FriedRice, Gobi {
    getPrice() : number {
        return FriedRice.getPrice() + Gobi.getPrice();
    }
}

How can I implement combo classes? Is there a way I can write a generic class/method to implement combo menu?

3
  • 1
    Given the use case it's probably not a good idea to implement menu items as classes, you will end up with an extremely rigid system. What happens when you need to add a new menu item or change up a combo? Ideally the menu would be externalized as configurable data and you would create generic classes to consume that data. Commented Oct 9, 2019 at 16:45
  • 2
    consider using composition for combos, not inheritance Commented Oct 9, 2019 at 17:23
  • JS/TS don't have multiple class inheritance, due to the single prototype chain. You could probably implement something with a Proxy or the like that behaves sort of like multiple inheritance, but you'll never get (const frg = new FriedRiceAndGobi(); console.log(frg instanceof FriedRice && frg instanceof Gobi) to return true; at most one of those classes will be in the prototype chain for any object. Composition is likely the way to go here; do you want an answer that shows how to do this? Commented Oct 9, 2019 at 19:12

1 Answer 1

1

Typescript does not have support for multiple inheritance.

There's a couple of different reasons why you would want multiple inheritance. Your example is however not one of them.

If, using your example, I would need a single class that encapsulates both ingredients, this is how I would approach this:

class CombinedItem {
   private menuItems: HasPrice[];
   constructor(menuItems: hasPrice[]) {
      this.menuItems = menuItems;
   }
   getPrice() {
      return this.menuItems.reduce(
         (acc, curr) => acc + curr.getPrice(),
         0
      );
    }
}

This could then be constructed as such:

const item = new CombinedItem([
   new Rice(),
   new Chicken()
]);

CombinedItem is a class that can take any combination of inputs. If you want something really specific, you can do:

class ChickenAndRice {
   private chicken: Chicken;
   private rice: Rice;
   constructor(chicken: Chicken, rice: Rice) {
      this.chicken = chicken;
      this.rice = rice;
   }
   getPrice() {
      return this.chicken.getPrice() + this.rice.getPrice();
    }
}

But I'm not sure why you would ever want this.

Thinking in the direction of inheritance for your problem is a common mistake, and right solution is to compose objects and classes together instead of inherit behavior.

Sign up to request clarification or add additional context in comments.

1 Comment

This is exactly what I was looking for. Thanks!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.