Can anyone explain me what's the point of overriding base class implementations (if its not abstract), because it's not ethical move to modify features of the parent class according to the wishes of derived classes. The best way is to make the base classes abstract and carry on the inheritance chain. Whereas when designing a class hierarchy initially we gather or elicit all the essential requirements/features that should be belonged to a base class. Therefore, in a middle of a project we do not need to change base class implementations. According to my knowledge, base class implementation should be a constant. Thus, under this aspect, there's no real use of "override" keyword in c#. If it's not so please explain me with an example.
Why we use virtual and override keywords in c#
inheritance
Related Solutions
You have created your own, unnecessary problem here.
- Everything must be runnable
- The default implementation of run requires proc
- Anybody implementing their own run can ignore proc (but all that useless code still adorns the class and any descendants).
- Your concrete, exception-throwing implementation of proc enables people to set up themselves up for runtime errors. Why do that?
OK, so you wanted to be helpful by providing a default implementation but you have bolted on implementation details which you know will not always be desired. You say you want to avoid code duplication but you have encumbered your hierarchy with code which will be obsolete as soon as somebody extends it.
I would strongly urge you to go the interface/abstract-base-class route here:
- Abstract base class runnable
- Abstract base class proccer
- Create proc-calling concrete implementation of runnable.
- Wherever possible (even in proc-caller class methods) refer to runnables and not proc-callers).
So your default run implentation can be used where desired but can be dropped without penalty. Also, this way people are forced to implement proc if they mix in proc-caller but you don't have to write that "Not implemented" version of proc - they can't compile their code if they do not implement proc. Why create that runtime trap when you can require them to fix things at compile time?
If you think there are other useful behaviours which should be available, you can avoid code duplication by providing "interfaces" in the same way I have shown for proc. Anybody who wants that can mix it in.
Having these abstractions implemented as interfaces allows more flexibility.
Interfaces allow programmers to use multiple inheritance of type in Java. This way you can treat any class as an instance of the interface regardless of its inheritance hierarchy.
You can implement any number of interfaces in a single class but you can only have a single superclass (as expressed by the extends
keyword).
At the same time, nothing prevents you from providing a skeletal implementation of any given interface
. Just write an abstract class
implementing it and use it as you please. You still have a single place to put the common parts and you don't make the clients of your API dependent on any actual implementation.
Besides, lists can have vastly different implementations and the details of the core behaviours can rely on mechanisms that are not at all similar.
Take a look at LinkedList
and ArrayList
for example.
The first one is backed by a number of interlinked objects. The latter stores its elements in an array. The way you access elements of these data structures is simply different. The effect of these operations is identical (and understandably, both these collections implement the List
interface) but the actual behaviour, the algorithms used to perform those operations are not really common.
Coincidentally, these concrete classes also have abstract
superclasses that serve as their skeletal implementations. LinkedList
is an instance of List
and AbstractSequentialList
while ArrayList
is a List
and an AbstractList
List
is an interface because of how general it is. It does not assume anything about implementation. AbstractSequentialList
and AbstractList
on the other hand do assume certain ways of element access. Hence they're implemented as abstract classes.
In response to the very beginning of your question
While defining the hierarchy, one can think to embed the abstract method(behaviour) in abstract class only because the derive concrete class posses that as core behaviour with it's specific implementation, one can think to embed the abstract method(behaviour) in interface only because derived concrete class does not posses that as core behaviour(but as peripheral) having it's specific implementation.
Above definition can be understood well with this example
One of the good reference also supports this point:
It's true that implementing multiple interfaces in a single class allows you to combine possibly unrelated sets of behaviour, or as you express it, peripheral behaviour but this is just a use case rather than the purpose of interfaces in its entirety.
Using interfaces to create mixins is a great use case for them and the only way to have multiple inheritance in Java but you're free to use interfaces outside this context.
It's perfectly valid to use an interface to define a set of core behaviours for a family of classes. In this case, I wouldn't say it is used as a mixin. It just defines a contract. At the same time, it can be used as a mixin by any other class if the programmer so desires. This is a matter of naming and the context in which you use these concepts.
The distinction between core and peripheral behaviour is completely separate from the distinction between classes and interfaces. What truly makes the difference here is that the set of implemented interfaces specifies what you can do with an object while the classes (abstract or not) in its inheritance hierarchy define how these things are to be done.
An abstract class with all its methods declared as abstract is just like a poorly implemented interface with its usage severely limited by the lack of capability regarding multiple inheritance of type.
Best Answer
Many times you will have dependencies in sub-classes, or may have to implement things differently.
There is nothing at all wrong with creating
virtual
methods in concrete classes and in some cases they are very useful. The difficulty is that many novice programmers violate the Liskov Substitution Principle when doing so. Remember that an overridden method should appear to do the same thing if used as a base method. It should not strengthen or weaken the preconditions of the base method.In the example I gave, the difference between the base class and the derived class was in the mechanics of how the car accelerated, not in the values allowed for
speed
. It did not throw any exceptions that were not expected by a calling class.This is a contrived example, but the principle is the same. Do use
virtual
andoverride
when needed. Don't violate the LSP.