abstract classes and interfaces best practices in

2019-03-21 08:14发布

问题:

So you've got an interface and an abstract class that implements a subset of the methods in the interface. You've also got some classes that inherit the abstract class and give implementations of the methods the abstract class doesn't give.

So what's the best practice here? I'm talking about issues like:

1) Should the abstract class implement the interface or should its child classes? Should every class? It seems to me that just the abstract class should. Of course, all of the classes could implement the interface, but that seems redundant because the children of the abstract will 'inherit' the interface because they extend the abstract class.

2) Given that the abstract class implements parts of the interface, should it also declare abstract methods for the methods it doesn't implement? It seems to me like this is right, but in a way this seems redundant because the children of the abstract will need to implement these methods in order to compile.

So what are your arguments for the best practice? The question boils down to: we've got an interface that defines what we want some classes to do, we've got a subset of the methods in the interface that define common behavior, and we've got a few different ways to define the non-common behavior. What's the best way to lay this out?

回答1:

The principle that should help you here id DRY: Don't Repeat Yourself (http://en.wikipedia.org/wiki/Don%27t_repeat_yourself).

In this context, DRY means that you should not do unnecessary work.

So for your 1st question the abstract class should implement the interface because it saves you from repeating the "implements X" clause at every concrete class.

As for the 2nd question, there's no point in repeating the interface methods in the abstract class that implements it. This is redundant work. Moreover when the interface evolves/changes you will need to change the counterparts (abstract) methods at the abstract class which is a headache. At some point you'll miss updating some of the method and the concrete class will need to implement these in vain.



回答2:

The abstract class should implement the interface, and provide concrete implementations of common member functions. IIRC it shouldn't need to declare abstract methods for the elements it doesn't implement, as these are assumed to be needed to be implemented by subclasses.



回答3:

The most flexible way to program for this is:

  1. Provide the interface
  2. Provide the abstract class that implements the interface
  3. Provide the concrete classes that either extend from the abstract class or extend from another class and implement the interface
  4. Alway (unless you cannot) declare variables/parameters/constants as the interface rather than the abstract class or concrete classes

There is no point in having the concrete classes implement the interface (more later). There is no point in having the abstract class repeat the abstract methods from the interface.

By doing #4 you ensure that all classes that implement the interface can be used - if you were to use the abstract class instead then classes that implement the interface but do not extend the abstract class cannot be used.

(later part)

The one argument for having the abstract class AND the concrete classes implement the interface is that if you were to later change the concrete class to no longer extend the abstract class then you could forget to also implement the interface, which, in some cases, could break the code without the compiler complaining. I don't know how I feel about that argument.



回答4:

Interface methods are implicitly abstract, so if an abstract class implements an interface, there is no need to satisfy the interface contract in the abstract class. An abstract interface is technically legal, but also redundant. It is fine for an abstract class to implement an interface as long as all subclasses would otherwise implement the interface, but the abstract class should not contain the implemented methods.

Interface methods are implementation specific (unique to the implementing class), whereas abstract states and behaviours are meant to be common, or shared amongst implementations. It would be an oxymoron to implement interface methods as common functionality.

The key question is what do you plan on doing with the interface implementations? If the base interface isn't used for anything besides defining an additional contract, I would say simply add abstract methods to the abstract class, otherwise the interface is redundant overhead. If you find a use case where you would want access to the interface methods, but not necessarily the common functionality, then maybe an interface is worthwhile.



回答5:

Do you have more implementations of the interface than the abstract class or subclasses thereof? Do your design need the interface? Otherwise, the interface contributes nothing to your design, and I suggest you simply get rid of it.

When it comes to your explicit questions, the abstract class should implement the interface. Classes extending the abstract class shouldn't.

You shouldn't redundantly declare abstract methods in the abstract class that already is in the interface.