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!

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.