I’ve created a console menu in both C++ and Python, but I suppose the language isn’t in too big role here, since I’m asking about the structure of classes.
So what I’m trying to achieve, is a menu similar to MS-DOS, where I can have parent menus (folders) and action menus (files). Here’s what it could look like in the console, once printed:
[-] Root directory
Open snakegame
[-] First sub directory
Print out stupid messages
[+] Closed directory in open directory
Shutdown computer
[+] These directories are closed
[+] You can't see the content inside them
Quit menu
So as you see, I got two types of menus here;
- Directory (MS-DOS folder) menus, which hold other menus inside them. When activated, they open/close. For example:
Root directoryis now open and you can see all the menus inside it. If it gets closed, the[-]turns into[+]and you can’t see any of the other menus. - Action (MS-DOS file) menus, which are linked to a function. When activated, they call the function they’re linked to. For example:
Open snakegamecould be linked to a functionstartSnakeGame(), which would close the menu and start the snake game.
I’ve already coded two working implementations to get the wanted result, and I was just wondering, which one should I use? The first way is, where I only have one class called Menu, and it has all the member variables and methods coded into one class. The other way is, where I got these two different types of menus separated into two classes, with a common base class.
Here are some member variables, I’ll split them into three sections (base class, directory class and action class) for now, but they can be combined into one class.
Base Menu:
parent= A menu (directory one) that holdsthis/selfinside a list/vector as a child (see below).label= Obviously the label which gets displayed when the menu is printed.selected= Boolean value which tells wether the menu is currently selected (fe. pointed by mouse).
Directory Menu:
subMenus= A list or a vector (in C++) that holds other menus inside it.open= A boolean value which tells wether the menu is open or closed.
Action Menu:
action= Pointer to the function which gets called when this menu gets activated.
As you can see, there are just few variables which differ from the other class, and it could be set so that if action == 0 (no action) then the menu automatically changes open to false/true depending on it’s current value. This way action menu would be terminated, and only down side would be that action menus would hold subMenus and closed without use.
This might be all about one’s opinion, but I’ve been thinking about this for a while, and couldn’t find one way superior to other, they both have their advantages and downsides, and both work well. So I’m asking about your opinion, and I would love to hear if anyone has any reasons why they’d choose one over the other. Basically I’m asking for the reasons, I don’t care about your opinion.
There will be no other menu types than folder and file, so the base class could not be used for anything else.
Edit: A simple Python and C++ example on how the menus are being used:
Python with only one class:
# Using default param. here to set "action = None" or "action = toggleOpen()"
root = Menu(None, "Root directory")
snake = Menu(root, "Open snakegame", startSnakeGame)
sub1 = Menu(root, "First sub directory")
printMsg = Menu(sub1, "Print out stupid messages")
...
Python with multiple classes:
# With multiple classes, action parameter no longer exists
root = DirectoryMenu(None, "Root directory")
snake = ActionMenu(root, "Open snakegame", startSnakeGame)
...
C++ with one class:
Menu* root = new Menu(0, "Root directory");
Menu* snake = new Menu(&root, "Open snakegame", &startSnakeGame);
...
C++ with multiple classes:
DirectoryMenu* root = new DirectoryMenu(0, "Root directory");
ActionMenu* snake = new ActionMenu(&root, "Open snakegame", &startSnakeGame);
...
2nd Edit: I had only implemented both ways in Python, and only the one-class way in C++. So I started to code the multi-class way in C++ too, just for fun and practice, and I ran into a problem; having one base class, I cannot add this to parent’s subMenus-vector, since base class doesn’t own subMenus, and base class cannot know DirectoryMenu.
So I will have to hack my way through this, which is a BIG minus. Unless someone can think of a good way to implement it?
BaseMenu::BaseMenu(BaseMenu* parent)
: m_parent(parent) // works
{
m_parent->addSubMenuk(this); // BaseMenu doesn't have Directory's addSubMenu()
}
The two ways are really close to each other in performance etc, so it was kinda hard to figure out.
However, there was one reason to pick one over the other: Logic and rules in OOP. I had to split it into 3 classes:
BaseMenu,ActionMenuandDirectoryMenu.Solving the “two classes cannot know each other” problem here could’ve been done like
iogane gamba puti fon gusuggested. However, defining abstract methodsaddSubMenu()andremoveSubMenu()inBaseMenuwould be just as much against rules as having only one class would, so that’s not an option over the other way.What I ended up with, is using callbacks and overloading the pointer(
*) operator. It now returns a pointer to the instance of the other class and calls it’s methods depending on the type.