简体   繁体   中英

Generics vs. Interfaces

I transitioned from Java 1.4(previous company) to Java 1.6 (new company). What I have observed that in case of 1.4 most of the proprietary frameworks were defined using interfaces and template patterns, whereas with 1.6 most of the frameworks are defined around generics.

While I am still trying to get a grip around Generics, my question is - Is this a right design approach? Interfaces make your design more flexible/decoupled. Whereas Generics, implement type safety and enforce you to pass around a specific type of class. Doesn't really help in decoupling your code. Is this correct?

One example -

public MyWizard extends SignupWizard<SignupSection, SignupObject, SignupListener, SignupView>{
}

instead the design would be more flexible if it was ..

public interface Wizardable{
  public SignableSection getSection();
  public SignableObject getSignableObject();
...
}

public MyWizard implements Wizardable{
....
}

I wouldn't say anything was generics vs interfaces, each have their different needs and uses. Using generic parameters in the way mentioned in the original post serves multiple purposes. It allows developers to define the base classes that make up the field object types of the class. Using this, the developer can accept class objects as parameters which they can use reflection on to create the actual objects and set the fields, or just accept the entire object to set in the first place. The problem which relates to needing class objects rather than doing new T() or such is known as type erasure .

Another benefit of using generics is that you don't need to typecast all the time when using fields or methods from a superclass -- you personally know their types, but Java doesn't have that type information stored anywhere. An additional benefit is that all your getter / setter methods can use the generic parameters and expose a more sensible front to other objects which rely on the fact that you set up specialised fields in the aforementioned object.

The problem with using interfaces to do the same thing that generics does is that you need additional methods to access the specialised types and cast them, before returning them (or check incoming types and then set fields to the objects). It's making the design more complex, and doesn't really help with decoupling at all.

As I mentioned in a comment, any subclasses will set those type parameters and expose nothing to the user. So you can have something like class MegaSignupWizard extends SignupWizard<MegaSignupSection, MegaSignupObject, MegaSignupListener, MegaSignupView> and everything remains perfectly valid with MegaSignupWizard having access to specialised methods in the classes without any need to cast. Now that's cool :)

Generics allows you to implement methods on the general type while interfaces only define the signatures. Maybe it's abused sometimes to act like Scala's trait , but mostly they serve two different purposes. If everything was an interface, there is going to be a lot of duplicated code or delegations to some helper class.

I've noticed that many of the new frameworks tend to use annotations instead of interfaces, but I haven't noticed them using generics instead of interfaces (whatever it means - please explain more).

With the help of generics, its possible to reduce some code duplication and to improve type safety, when you have one interface with generic type parameters and the same interface will work for lots of different types. The collections in the java.util package are a good example of when generics are useful.

In the case of annotations, sometimes I feel they are overused and an interface would be better - for example with an interface it's easy to know what parameters a method should take - but on other cases an annotation is more flexible and powerful.

I think it's generics and interfaces, since any interface can make use of generics itself. The problem I see when you start to use generic (abstract) classes you lose the flexibility of using composition. While there is nothing bad about inheritance as such you have to design for it and there are many pitfalls.

Take a look at Jung2 to see where Generics become really powerful. Basically, any object can be a vertex or an edge which makes for some really interesting ideas in network algorithms. You couldn't do this with just interfaces.

I'm not sure your above use looks good either. If you're extending from an object or implementing an interface you don't really want to be passing objects like that. Generics are used to implement a class with abstract type, like a collection, that could act on anything. What happens if I pass SignupWizard<int, int, int, int> which is perfectly valid?

For that particular idea, perhaps you do want to use interfaces. Have an interface defining wizardaction, each object implementing it and mywizard being able to .addaction(int position, wizardaction action). In fact that is definitely an interfaces problem.

I'd agree with the others - generics have been used when they're needed by libraries.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM