views:

544

answers:

6

I have an interface A, for which I have to supply a few different implementations. However, those implementations share some helper methods, so I moved those methods to an abstract base class.

Interface A {
 void doX();
}

abstract Class B implements A {
 protected void commonY() {
  // ...
 }

 @Override
 public abstract void doX();
}

Class C extends B {
 @Override
 public void doX() {
  // ...
 }
}

Class D extends B {
 @Override
 public void doX() {
  // ...
 }
}

My code works as expected, but I have a few questions:

  • Should I declare the abstract Method doX() in Class B? Why (not)?

  • Should I also explicitly declare "implements A" on Class C and D? Why (not)?

Big thanks in advance!

+4  A: 
  • Should I declare the abstract Method doX() in Class B? Why (not)?

No. It's an abstract class - defining the interface will mean that all subclasses will need to implement those methods. In other words, it's redundant.

  • Should I also explicitly declare "implements A" on Class C and D? Why (not)?

No, again - because your superclass (Abstract base class) implements that interface, your concrete subclasses will be guaranteed to implement that interface.

Phill Sacre
A: 

An abstract class implementing an interface must implement that interface. Specifically, it must have a public method for every method-name-and-signature specified in that interface.

Inheritance is transitive. You do not need to write that class C implements interface A if class C derives class B which implements interface A. However, there isn't much harm to it either.

Justice
I don't think an abstract class must implement every method in an interface. I've just tested this and it seems you can implement an interface in an abstract class without actually declaring any of the interface's methods.
Phill Sacre
Hmm you're probably right. I was going off of my memory of Java and my current experience in C#. In C#, an abstract class implementing an interface is required to implement all the interface methods (even by just marking them abstract).
Justice
A: 

I would not declare doX() in B and not add "implements A" on C and D because you should not repeat yourself.

The abstract doX() in B adds nothing, as it's already specified by "implements A". The same is true for adding "implements A" to C and D.

The only possible use for those clauses would be documentation: If you want to make it very explicit that C (or D) is-a A, then you could add the implements, but you should be aware that it really doesn't matter to the compiler.

Joachim Sauer
+7  A: 

I think it would be better to do it as follows:

Interface A {
        void doX();
}

abstract Class B {
        protected void commonY() {
                // ...
        }
}

Class C extends B implements A{

        public void doX() {
                // ...
        }
}

Class D extends B implements A{

        public void doX() {
                // ...
        }
}

You shouldn't mix the interface (signature of methods) with the implementation.

kgiannakakis
The benefit of this solution is that when class X that implements Z but that requires the functionality of method commonY is introduced, it to can specialize class B.
Nick Holt
This would depend on usage. If the B is a base to multiple implementations of A, then it should implement A. Same as AbstractList or AbstractCollection.
Robin
+1  A: 

I'll just throw in the other option.

Turn abstract class B into an AUtil class that doesn't implement A. The method signatures may require an additional argument of type A to work with.

C and D implement A, and instantiate an AUtil internally. This does allow C and D to extend other classes.

JeeBee
This is definitely how I would do it. I'm a strong opponent of using inheritance for the sake of providing methods. That's what static utility methods are for!
jdmichal
+1  A: 

I agree with JeeBee: consider implementing your helper methods somewhere other than an abstract base class.

If your helper method commonY() only exists in abstract base class B, all classes which implement Interface A will have to also extend base class B in order to take advantage of that implementation of commonY(). But, you might not always want to be forced to extend class B.

Also, what if you want to change the implementation of commonY() in the future? You will then affect lots of implementations of interface A. But if you don't control all these implementations of interface A, you may affect their functionality (in a bad way) without intending to.

Using an abstract base class in this situation may simply take away some flexibility without giving you anything in return.

Chinnery