views:

128

answers:

6

I would like to write an abstract class (or interface) which either

  • Forces all implementing classes to provide a field (ideally static) of a particular type and name (maybe by throwing a compile-time error if it's missing?), or
  • Automatically provides such fields in implementing classes.

An example would be:

public abstract class A {
    abstract int counter;
}

public class B extends A {
    public int getCounter() {
        return counter;
    }
}

in which case B's getCounter() method would return a (static or instance) counter specific to the B class, and not a value inherited from A. Is there any way to do this in Java?

+8  A: 

There is not really a good way to do that, nor do I believe there should be. You can accomplish the same thing using abstract methods and writing your algorithms in the base class so that they take advantage of the delegated methods.

Perhaps if you provide more details on why you think you need to do this, we can help you craft a more correct solution.

For example:

public abstract class A {

    protected abstract int getCounter();

    public void doStuff() {
        int counter = getCounter();
        for (int i=0; i < counter; i++) {
            // do stuff
        }
    }

}
Kevin
Each class that implements A needs its own copy of a (static, ideally) variable named `counter`, and a getter for that counter. To minimize the duplicate code, I was hoping to have some way to write one getter method in A that actually returns B's counter. This is because there will be one "template" abstract class (or interface) A but many similar implementing classes which are like B.
Matt Ball
There seems to be no need for the variable to be static. My example should do what you want.
Kevin
+1  A: 

Make a HashMap with the class as key, and the counter as value.

Thorbjørn Ravn Andersen
That sounds horrible and rather inelegant to me. I'm trying to write less code, not more.
Matt Ball
but it sounds rather appropriate to me. "less code" is not always appropriate. (btw, Thorbjorn - sorry, out of upvotes for today)
Bozho
this.getClass() can get you quite a bit of the way.
Thorbjørn Ravn Andersen
also be very careful if your "less code" ends up in actual functionality being hidden away causing those who gets to maintain your code to hunt you down to either kill you or make you fix it yourself.
Thorbjørn Ravn Andersen
bozho, no problem. I'd appreciate a link, however, if your answer was inspired by mine.
Thorbjørn Ravn Andersen
Sure. I acknowledged you for the original idea.
Bozho
+1  A: 

An interface's main purpose is not to tell its implementors what to do. It is to tell other classes what its implementors can do. Also, it should not specify any implementation details. That said, it shouldn't and can't impose any variable declarations.

If you want a per-subclass counter, then declare a Map in the superclass, with key=subclass's Class, and value=the counter value (as suggested by Thorbjørn Ravn Andersen's answer)

Bozho
Which is why I'm thinking primarily about doing this with an abstract class.
Matt Ball
abstract classes also specify "an interface". Although not strictly through the interface keyword.
Bozho
A: 

Try one of the many tools listed here:

http://en.wikipedia.org/wiki/List%5Fof%5Ftools%5Ffor%5Fstatic%5Fcode%5Fanalysis#Java

I am assuming this is in a development environment with multiple developers.

Woot4Moo
In what way is this relevant.. ?
Bozho
Yes it is relevant. It is *A* way to enforce the things he wants
Woot4Moo
I'm not the only one in my shop, but I am the only one (in the foreseeable future) writing classes which implement A. I want to force myself to write consistent implementations.
Matt Ball
A: 

As others have pointed out, this isn't directly possible in the language without a fair amount of extra work.

My suggestion is that you follow Pace's suggestion: instead of specifying a counter, specify it as a method in an interface.

The only difference I'd suggest is that you rename it to something which more correctly reflects your intention. Something like:


    protected abstract getNumberOfInstancesOfThisClass();

You could even code up an automated unit test generator to check that it's been correctly implemented, something you'd have to do even if you could create a static member in an abstract class.

CPerkins
A: 
public abstract class A {
   private static Map<Class,Integer> map = new HashMap<Class,Integer>();
   protected A() { map.put(this.getClass(), 0); }

   public int getCounter() { return map.get(this.getClass()); }
   public void setCounter(int n) { map.put(this.getClass(), n); }
}

public class B extends A {
   ...    
}
Itay