An interface is a contract. Usually, the interfaces define a specific behavior, shared by all the implementations of the interface. For example,
IResizable would define a contract that tells that an instance of a class implementing this interface would be able to resize itself.
A class can implement zero, one, or several interfaces. When a class implements a given interface, it promises to follow the contract defined by this interface. For example,
class Window : IResizable means that a UI window can be resized. Similarly, there can be a
class Button : IResizable, meaning that the UI buttons can, as well, be resized.
Different classes implement the same interface differently. For example, a
Square and a
Rectangle can both be resized, but the algorithm behind the resize action would not be the same—you can’t, for instance, resize a square in a way it would stop being a square and would start being a rectangle. The sole difference in the implementation, however, doesn’t mean you should use different interfaces. For instance,
IEquatable can both be applied to integers and to strings; however, in the first case, the comparison would be performed on the value itself, whereas in the case of the strings, one would probably first look at the length of the string, then the hash, and only then compare the actual strings, either byte by byte or character by character. Different implementations, same interface.
What makes one to decide whether two classes can implement the same interface is, (1) the contract itself, down to the individual arguments, as well as (2) the common logic.
For instance, a resize action for a rectangle might look like this:
void Resize(double width, double height);
Such signature makes no sense for a square. You can’t do
square.Resize(20.5, 18.4)—there is no expected behavior for such action. Either you have to ignore one of the arguments, or you need to throw an exception if two values differ. The first case is simply wrong; the second is ugly.
Therefore, a square would rather have something like:
void Resize(double size);
The very same interface would, therefore, apply to a square or a circle, but a different interface would be used for a rectangle or an oval.