In my case, I chose to extend GuiceServletContextListener and
implement Module in one place.
Gili
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.
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
> 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
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.
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