class List
{
void insert(type);
void remove(node*);
bool is_empty();
int size();
type peek();
}
class Stack : private List
{
void push(type);
type pop();
bool is_empty() { return List::is_empty(); }
int size() { return List::size(); }
type peek() { return List::peek(); }
}
I have 2 class: List, and Stack (inherits List).
In Stack I want to limit the operations to push/pop, size, peek, is_empty which are already implemented in List.
Additionally List has other operations ie. remove that I don't want Stack to have access to.
Currently I have set Stack to privately inherit from List.
Problem/Question: Is this the right approach to access from Stack ... the operations from List: size, peek, is_empty. My solution as of now is to redefine the functions inside Stack to call their respective functions from List. I just want to know from you experienced programmers is this the right approach or should i not even worry about applying such restrictions and leave it up to the user in which case I can just publicly inherit but the user would have access to remove operations from anywhere within the stack, which defeats the whole purpose of a Stack class. Any insight/suggestions is greatly appreciated.
1) Your classes are completely useless right now, because all members are private.
2) Private Inheritance is almost the same thing as composition. You might as well say Stack HAS a list, rather than Stack IS a list (but doesn't want to admit it) - I think that is the better approach, though you might need private inheritance for some crazy hack or something.
BTW: A peek function doesn't make any sense with a list - what does it mean to peek on a list?
I must agree with Suzukiz on this one. +1 to privately inheriting. I believe it is a better approach than containing. I would have gone that route too. There is nothing wrong about privately inheriting from a class.
And I do believe important to hide the members of List so Stack is appropriately used.
I said peeking doesn't make any sense on a list - it does on a stack, but his LIST class actually has a peek function itself. Hence I say, what does it mean to peek on a list?
And web...
I believe it is a better approach than containing.
how so?
Benefits in this case: 0.
Problems: Stack has to deal with the interface of List (only on a private level, but it still has to) and it's less readible too.
My opinion is that inheritance makes the code cleaner because conceptually, the queue is in fact a list, just a list with a very special use. I don't see why a queue must have an internal list. I see clearly, though, that a queue is a list. It is therefore a natural move to inherit from a list class.
Newbies almost always overuse inheritance. This is a classic example of when it should not be used. It fails the Liskov substitution test. The stack cannot be used in place of a list.
Also remember that inheritance can be done for several reasons. One of them is code reuse. Are you allowed to use inheritance only in cases where you can squeeze off ALL benefits of inheritance? Can you not use inheritance just to obtain one or two benefits?
I say: You can use inheritance to obtain partial benefits, so I continue to support inheritance in this case.
Again, how exactly is there "more" or "better" code reuse here compared to composition? You make no sense. Inheritance to improve code reuse only makes sense when talking about polymorphy.
Great hanst99. Once more, that's your opinion. Note that I have NEVER said this is better than containment. I said it is my PREFERRED choice in lack of strong arguments against it because I understand it better than containment in this particular case.
The thing is, a stack IS NOT a list. Think duck: If something looks like a duck and behaves like a duck you can call it a duck. A stack neither looks nor behaves like a list. A stack can USE a list internally to manage it's data, but a stack IS NOT a list.
Aha! So this IS in fact, a matter of opinion. You believe a stack is not a list. I think a stack is a form of list. So does the OP. So does Microsoft's .Net framework. We all believe stacks and queues are forms of lists. Only thing is that .net call them ICollection and the OP calls them List.
Because you don't believe they are lists, you root for containment; the rest of us root for inheritance.
And one more detail here: We all know that polymorphism here is not an option because the OP is explicitly breaking it using private inheritance, so all polymorphism-related arguments are moot, including the Liskov Substitution Test. The OP is not trying to achieve polymorphism.
I also believe that a Stack is not a list. A Stack may use a list internally, but is not one. You can also use an array internally, is a Stack an Array?
Just from looking at the interface in the STL:
1 2
template < class T, class Container = deque<T> > class stack;
An STL stack is not a list, in fact uses a deque internally. The STL calls this a container adapter but simply speaking, it's just composition.
@PanGalactic: Ok, then show polymorphism using private inheritance.
@darkestfright: Great! I probably would be ruling for hanst too if I didn't believe stack are lists. I think they are lists so I am ruling the other way. :-)