Module versus AbstractModule

852 views
Skip to first unread message

Josh

unread,
Feb 15, 2011, 12:40:14 AM2/15/11
to google-guice
This question is somewhat related to Guice, but I think this is a good
place to ask...

I'm currently working on an API where I need to wrap the usage of the
API to catch any exceptions that might occur, similar to Guice's use
of Modules to exercise the Binder EDSL. This has got me wondering
though, is there any good reason for needing an interface and a
support class (ala Module/AbstractModule) in such an API? Are there
any Guice use cases that might require implementing Module instead of
extending AbstractModule?

Regards
Josh

cowwoc

unread,
Feb 15, 2011, 7:17:25 PM2/15/11
to google...@googlegroups.com
Hi Josh,

In my case, I chose to extend GuiceServletContextListener and
implement Module in one place.

Gili

Stuart McCulloch

unread,
Feb 15, 2011, 7:34:23 PM2/15/11
to google...@googlegroups.com
only providing the abstract class limits peoples choices (you can implement many interfaces, but only extend one subclass)

an interface makes it easier to bolt functionality onto an existing class - it also makes it easier to create thin dynamic proxies

Regards
Josh

--
You received this message because you are subscribed to the Google Groups "google-guice" group.
To post to this group, send email to google...@googlegroups.com.
To unsubscribe from this group, send email to google-guice...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/google-guice?hl=en.




--
Cheers, Stuart

Josh

unread,
Feb 15, 2011, 7:56:12 PM2/15/11
to google-guice
Thanks for the responses. I guess my question has been answered.

Josh

On Feb 15, 4:34 pm, Stuart McCulloch <mccu...@gmail.com> wrote:

Thomas Broyer

unread,
Feb 16, 2011, 8:25:58 AM2/16/11
to google...@googlegroups.com


On Wednesday, February 16, 2011 1:34:23 AM UTC+1, mcculls wrote:
On 15 February 2011 05:40, Josh <paces...@gmail.com> wrote:
This question is somewhat related to Guice, but I think this is a good
place to ask...

I'm currently working on an API where I need to wrap the usage of the
API to catch any exceptions that might occur, similar to Guice's use
of Modules to exercise the Binder EDSL. This has got me wondering
though, is there any good reason for needing an interface and a
support class (ala Module/AbstractModule) in such an API? Are there
any Guice use cases that might require implementing Module instead of
extending AbstractModule?

only providing the abstract class limits peoples choices (you can implement many interfaces, but only extend one subclass)

an interface makes it easier to bolt functionality onto an existing class - it also makes it easier to create thin dynamic proxies


Interfaces in Java come at a cost though: you cannot change an interface without breaking any class implementing it.

With an abstract class, you can add methods with default implementations (even a throw new UnsupportedOperationException()) and you won't break anyone who extended it.
You can also change an abstract method into a concrete one, whose default implementation now calls a new method (it's generally the case when you add an overload and want to deprecate the previous one in favor of the new).

The best of both worlds is IMO to provide both an interface and a support class and suggest people to preferably extend the abstract class (see for instance the warning in the javadoc for javax.lang.model.element.ElementVisitor; others are talking stronger approaches, e.g. org.hamcrest.Matcher and its _dont_implement_Matcher___instead_extend_BaseMatcher_() method)

Philippe Beaudoin

unread,
Feb 16, 2011, 9:04:10 AM2/16/11
to google...@googlegroups.com
On Wed, Feb 16, 2011 at 5:25 AM, Thomas Broyer <t.br...@gmail.com> wrote:

> The best of both worlds is IMO to provide both an interface and a support
> class and suggest people to preferably extend the abstract class (see for
> instance the warning in the javadoc for
> javax.lang.model.element.ElementVisitor; others are talking stronger
> approaches, e.g. org.hamcrest.Matcher and
> its _dont_implement_Matcher___instead_extend_BaseMatcher_() method)

+1

This last example screams for support of some documentation annotation
that you could place on an interface and which would encourage people
to use "extends" instead of "implements". Something like:
@DefaultImplementation(AbstractModule.class)
public interface Module {...}

And then:
public class MyModule extends SomeOtherBaseClass implements Module {
}

would generate an error, unless it is annotated with, say:
@Reimplements(Module.class)

No clue if this holds water, but I'm curious to know if something like
that has ever been proposed? (And sorry for hijacking the Guice forum
with such java fundamentals questions...)

Philippe

Sam Berlin

unread,
Feb 16, 2011, 9:15:13 AM2/16/11
to google...@googlegroups.com
Guice allows this in the DI-way by using @ImplementedBy.  But it unnecessarily ties the API to the implementation, which is an even worse transgression IMO.
 sam

Philippe Beaudoin

unread,
Feb 16, 2011, 9:24:45 AM2/16/11
to google...@googlegroups.com
Agreed. I guess my terminology choice was poor.
@DefaultBaseClass(AbstracModule.class) would have been better. It
looks like it should be a language/compiler feature rather than a
feature of the DI framework.

Hilco Wijbenga

unread,
Feb 16, 2011, 12:40:52 PM2/16/11
to google...@googlegroups.com, Thomas Broyer
On 16 February 2011 05:25, Thomas Broyer <t.br...@gmail.com> wrote:
> On Wednesday, February 16, 2011 1:34:23 AM UTC+1, mcculls wrote:
>> On 15 February 2011 05:40, Josh <paces...@gmail.com> wrote:
>>>
>>> This question is somewhat related to Guice, but I think this is a good
>>> place to ask...
>>>
>>> I'm currently working on an API where I need to wrap the usage of the
>>> API to catch any exceptions that might occur, similar to Guice's use
>>> of Modules to exercise the Binder EDSL. This has got me wondering
>>> though, is there any good reason for needing an interface and a
>>> support class (ala Module/AbstractModule) in such an API? Are there
>>> any Guice use cases that might require implementing Module instead of
>>> extending AbstractModule?
>>
>> only providing the abstract class limits peoples choices (you can
>> implement many interfaces, but only extend one subclass)
>> an interface makes it easier to bolt functionality onto an existing class
>> - it also makes it easier to create thin dynamic proxies
>
> Interfaces in Java come at a cost though: you cannot change an interface
> without breaking any class implementing it.

That's a benefit, not a cost. If the public API of a library changes
then that should not be (semi) hidden but out in the open.

> With an abstract class, you can add methods with default implementations
> (even a throw new UnsupportedOperationException()) and you won't break
> anyone who extended it.

You don't know that. Since the new method is probably something
"obvious" I might already have implemented it. This is really evil
because my code might still compile but not work any more. Moreover,
(as Stuart also mentioned) you're forcing me to use my one chance at
inheritance. It's not nice when a library forces me in a direction I
don't want to go.

Changing a base class is always risky as it changes the foundation of
the extending class. Similar to the fragile base class problem.

> You can also change an abstract method into a concrete one, whose default
> implementation now calls a new method (it's generally the case when you add
> an overload and want to deprecate the previous one in favor of the new).
> The best of both worlds is IMO to provide both an interface and a support
> class and suggest people to preferably extend the abstract class (see for
> instance the warning in the javadoc for
> javax.lang.model.element.ElementVisitor; others are talking stronger
> approaches, e.g. org.hamcrest.Matcher and
> its _dont_implement_Matcher___instead_extend_BaseMatcher_() method)

That's a little better but I would prefer a more DI approach. Then the
library class can be concrete and even final. On top of that, it's
very easy for the developer (i.e. the library user) to understand what
still needs to be implemented.

public interface Abc { void myAbstractMethod(); } // All abstract stuff.
public interface Xyz extends Abc { void myConcreteMethod(); } // All
concrete stuff.
public final MyXyz implements Xyz {
private final Abc abc;
public MyXyz(final Abc abc) { this.abc=abc; }
public void myConcreteMethod() { ... implementation ... }
public void myAbstractMethod() { abc.myAbstractMethod(); }
}

Simple, reliable, testable, and no weird warning methods needed. :-)

Now the library developers can safely extend/change interface Xyz and
provide a default implementation in MyXyz. The compiler will warn any
library user who has implemented Xyz directly.

cowwoc

unread,
Feb 16, 2011, 1:29:54 PM2/16/11
to google...@googlegroups.com

In my opinion, that is an awful idea :) There is absolutely nothing
wrong with using the interface. Throwing compiler errors into the mix
will not transform poor developers into better ones. If you're coding in
Java you should really know the difference between interfaces and
abstract classes. If you use a class you should really read its
specification (Javadoc). If you don't, it's your loss.

Gili

Josh

unread,
Feb 16, 2011, 5:53:54 PM2/16/11
to google-guice
I get the idea here, but Module is a different sort of type than a
visitor since (it is assumed) that Module will ever only contain one
method. It's akin to any of the various SAM types: Predicates and
Comparators and such. That said, it seems the harm with offering
Module only as a concrete class is that it doesn't allow an
implementation of a Module in a class that extends something else, as
Gili pointed out. I prefer single purpose types for my Module
implementations, but it's fair enough that others don't.

Josh
Reply all
Reply to author
Forward
0 new messages