The best answer here is the one by C Pallini.
It needs one subtle recommendation: do not use abstract classes where interface can be used.
It looks like the inference from the rule of thumb offered by C Pallini, but it is not.
Sometimes, you need a common behavior for derived classes which you can use polymorphous container. Interface cannot be used here, because late binding is involved. At the same time, you can use the same very abstract class to express a common interface to all of the classes to be passed, say, as a parameter to some other class not related to your hierarchy.
Event if the public/internal set of features matches your goal — don't do it! Why? In this way you would cut yourself from extra flexibility: ability to create another class not related to your existing hierarchy implementing the same interface.
One could also create a "poor virtual" abstract class (a class with method-only members; all of them being abstract), as a logical equivalent of interface (this is how C++ interfaces are implemented). Same thing: don't do it! Interfaces are interfaces: they add extra isolation from implementation. Consider the following example:
IMyInterface {
void MethodA();
void MethodM();
}
class MyInterfaceImplementation : IMyInterface {
public void MethodA() { }
void IMyInterface.MethodB() { }
}
MyInterfaceImplementation impl = new MyInterfaceImplementation();
IMyInterface intrfHandle = impl;
intrfHandle.MethodA(); intrfHandle.MethodB();
impl.MethodA();
The fact that last (commented out) call will not compile is really good, it help isolation of class instances represented by interfaces from implementations, another reason to prefer "interface for interfacing".
—SA