Why is programming to abstract classes instead of

2019-07-20 04:48发布

问题:

I am going through the differences between Struts1 and Strust2 , i found out that , A common problem in Struts 1 is programming to abstract classes instead of interfaces.

Could anybody please let me know , Why is programming to abstract classes instead of interfaces is a problem ?

回答1:

Problem?

Programming to Abstract Class is not a problem at all, it is depends how you design your object relationship.

Difference

Abstract Class provide partial implementation, which promote reuse of the code, while Interface only provide methods without any implementation in which promote encapsulation.

So When Use Abstract?

You should use abstract class when there is certain implementation uncertain to its subclass and other part of the behavior is same for all of the subclass.



回答2:

In Java, one of the reasons is that you don't have multiple inheritance, so the moment you extend an Abstract Class, that's it, there's no way you can extend any other.

The only way to work around this, is through a complex tree of dependencies that are very bad for your architecture in the long run (it'll get really hard to figure out quickly what depends from what).

If your class C needs to expose the interface of abstract class AC (interface in the broad sense of the term), then you can make class C extend AC. But now you also want your class C to expose the interface of another class AC1... and there's no simple way to do so. You'll need to resort either to composition (which I actually prefer to extension), or you'll have to make AC1 extend AC... or some other weird voodoo to get this to work.

In my opinion, architectural clarity and extensibility are the main reason one would prefer to use Interfaces instead of Abstract Classes to compose your solution. There's also the question of how robust your code may become. If you extend a Class from an external package/jar, you might be stuck with that particular version of the implementation, since changes to the Abstract Class might break your code.

On the other hand...

Not all is perfect in the land of Interface usage. In some cases, trying to be a purist and use solely Interfaces with no extends at all, might lead to some unnecessary code duplication. There's really no magic rule.

To address this issue and still maintain flexibility (not compromising yourself with your only available extends), you can reuse code through composition instead of inheritance. Implement an interface, have a class with the common base code, make your "inherited" methods (from the interface), proxy to that common class (that becomes an attribute of your class), and you have the best of both worlds.

Finally, my goal as a developer (particularly in Java), is to one day be able to express an opinion that Joshua Bloch hasn't expressed much better before, to this day, I have failed to do so, so I leave this link to Effective Java, which explains this last point much better then I'm able to:

Effective Java



回答3:

I am not familiar with Struts, so can't comment on the specific problems of Struts 1. However, in general, abstract classes include implementation too, which interfaces can't. This

  • creates more dependencies, which may hurt maintainability and reusability,
  • makes them less resilient to change, which in turn may break client code in unexpected ways,
  • last but not least (as @pcalcao rightly noted), this approach disallows inheritance from another class.


回答4:

Wrong might be too strong a word. Context always matters.

Why either/or? Can't you do both? Write an interface and provide an abstract implementation with default behavior, a la java.util collections.

You can only singly inherit implementation; interfaces allow multiple inheritance. So that might be one reason to prefer interfaces. Another is that you may not always want default behavior.

Take Struts with a grain of salt. Struts 1 was the first web model-2 MVC framework back in 2000-2002. It didn't have the benefit of all that's been learned since then (e.g. Joshua Bloch and "Effective Java.") Struts 2 was not that radical a re-write, because it had to maintain backward compatibility.

I wouldn't hold up Struts as an example of good design or best practices. Look elsewhere.



回答5:

You can have the best of both worlds if you have your abstract classes implement an interface; in stead of subclassing the abstract class, you can choose to implement the interface. That way you can still subclass another class.



回答6:

there is nothing wrong to use abstract classes, but it may be not the best solution

abstract class may partly implement methods while interface do nothing than declare methods

When it make sence to supply implementation use abstract classes. Or do both, define an interface AND (partly) implement a (abstract) class implementing this interface



回答7:

In a nutshell and conceptually, it is often described as:

  • abstract classes: IS-A
  • interfaces: HAS-A (or can-do, -able...)

Example: Class Dog and class Cat extend abstract class Animal, for both are animals (Dog is an animal). Abstract class Animal would have a methods like walk() or sleep(). Class Animal can implement interface Washable with a method wash(). This method would be implemented for each animal, for one would use mud, water, its tongue, his fellow monkey's fingers...

As it has been said, interfaces allows more modularity. They are preferred in large projects since it allows less code breaks and mock-implementations. (Ex. I have to use a service of yours but you didn't had enough time to implement it. If we use an interface, I can create this mock-impl with the method getProductId() which always returns the same number. When you'll be done, we susbsitute my mock by your actual service.). Mocks are great for testing purposes.

Practical examples:

  • Decorator pattern (abstract class): http://en.wikipedia.org/wiki/Decorator_pattern
  • Strategy pattern (interface): http://en.wikipedia.org/wiki/Strategy_pattern


回答8:

Unless an abstract class exposes public fields directly, if one defines an interface that includes all the public members of the abstract class and has the class implement it, one will be able to do just about everything with a variable or parameter of the interface type that one can do with the abstract class type. On the other hand, if it becomes necessary to define a type which can do everything the abstract class can do, but which has derive from some other base class, such a type will be usable with routines which expect parameters of the interface type, but not with those which expect the abstract class type.

In short, a variable or parameter of an interface type is in some ways superior to one of an abstract type that implements the interface and has the same public members; it is in almost no way inferior. Consequently, one should use the interface type absent a good reason not to.