2

In Java, is there a design pattern or trick that can handle the "I want static methods declared in interfaces so that my classes are forced to implement them?" I've read a lot about static classes in interfaces lately, but nothing that can satisfy this particular issue.

Example: Suppose I'm making a game, let's call it StarClone. I have a save file that lists the last known location of soldiers and beasties. Suppose one of those beasties is a unit called a Zerkling. My game AI is interested to know how many Zerklings exist in its forces, because if this number passes a certain threshold it will perform a "Zerk rush" attack at the player's base. For this example, the value is stored as a static integer which is a member of the Zerkling class.

Now, I would really love to enforce the fact that each unit's class has a method, countsHowMany, which takes this save file and sees how many of that particular unit exists--at least that's what it could do, but each class will implement this however it wants. Since the member variable is static, it seems sensible that the method that sets it is also static. I may not have an instance of a Zerkling upon which I may invoke a non-static countsHowMany method, as a count of 0 is possible. We could argue that the variable is probably initialized to 0 to start with, but think of cases where the initial value is not usable in the same way; e.g. in my actual project, I'm retrieving game sprite images; these start out as null.

It seems like a desirably efficient design to simply have a list of all of my soldier and beast classes in one spot, grouped into a collection by an interface which we can call ICountMyself. So we can do something like:

for ( Class <? extends ICountMyself> currentClass : listOfUnitClasses )
{
    currentClass.countHowMany( savedGameFile );
} 

But of course, static methods in interfaces don't currently work like this in Java.

One possibility that might work around this is to have the method countsHowMany be non-static. Then, I when I am iterating through the classes, I can create a new instance of the class, invoke its respective countsHowMany method, and the non-static method would in turn modify the static member variable. This seems a little wasteful; imagine if I had to modify a cookbook in this fashion to use a different amount of salt for its recipes. I would be forced to flip through each page, find every entry of salt, cook the dish, scratch out the quantity and write in a new one, and finally throw the uneaten food into the garbage.

Any other way I can tackle this issue?

Thanks in advance!


Edit: Thanks to all for your swift and insightful answers! I am reminded of the fact that a valid answer to any question in computer science is "Well, it depends…" I originally did not wish to be so specific that my question lost its general applicability, but please allow me to elaborate somewhat on the original problem.

As I mentioned briefly, the original issue dealt with image sprites being loaded. The images are pre-loaded (for performance reasons) by an Image Manager package that I've put into a jar, hoping to have something general enough to re-use between games.

In trying to adhere to a more object-oriented approach, the game logic delegates responsibility for drawing units to the objects themselves. The base unit class takes care of implementing the drawsToScreen interface methods. In turn the base unit class calls an abstract method, getSprite(), which is implemented by the concrete classes. I trust each object to know its own state, thus it can determine which sprite frame to return from this call.

All that's left is getting the correct image references from the Image Manager, which is why I was curious about how to use static methods to set static member variables in this way. This saves me the trouble of hunting through a hash table of images every time I want to find the one I want. Ideally, a Zerkling would know what images to use to draw itself to the screen before I've even instantiated one.

4
  • "My game AI is interested to know how many Zerklings exist in its forces", then the "Game" class is responsible of the count, not the "Zerkling" class Commented Nov 7, 2014 at 18:26
  • If you have a bunch of classes that all define the same static method, you can't call it polymorphically, which means that you'd have to call Zerkling.countHowMany(), OtherUnit.countHowMany(), YetSomethingElse.countHowMany(), explicitly in your code. Or did you have any other thought for how you plan to do this? Commented Nov 7, 2014 at 18:31
  • @RC you are quite correct in that I need to be more aware of the reason I need the information, not just the way I am using it. I will try to elaborate in an edit. Commented Nov 7, 2014 at 22:57
  • @ajb You give me a good idea. Revisiting the problem, I realize I overlooked one important thing; how did the classes get into the list in the first place? I assuming that I'm only calling one function, it's just as easy to say Zerkling.countHowMany(), Metalisk.countHowMany(), etc, as it is to say classList.add(Zerkling.class). I think it would get messy if there is more than one task I want to perform, and especially if a second relies on the first. I would have to make sure I am correctly manually adding and deleting the classes from my blocks; that's why I was hoping to use a collection. Commented Nov 7, 2014 at 22:58

4 Answers 4

2

I don't think you want this in the Zerkling class. An object of class Zerkling represents one unit, but it sounds like you may want an object that represents the whole group of a certain type of unit (the group size could be 0), with one such object per type of unit. The countHowMany() method would be an instance method defined for your "group" class. You could define an interface or abstract class with a countHowMany() method, that each of the other classes GroupOfZerklings, etc., would extend.

That's not the only solution. If the only thing you want to do is keep a count for each type of unit, a Map<Class,Integer> might do the job. The key would be Zerkling.class or whatever. But the "group object" is one possible solution; whether it's the best solution depends on just what your needs are in the rest of your application.

Sign up to request clarification or add additional context in comments.

1 Comment

The map of units would be a good idea if I wanted to touch as few classes as possible when making changes to the different types of units. The reason I wanted to have the count in the actual class in this example is because it more closely reflects my original problem of having some sort of static information in general to store in the class, that had to do with that class alone. I'll try to clarify in my next edit.
1

It sounds to me that you have run into one of the problems that you get when you overuse / misuse static variables.

The problem you have run into is that you cannot do polymorphism for static methods in Java:

  • There is no way of saying that all subclasses of a given class must implement a given static method.

  • There is no polymorphic way of calling a static method. A call to a static method in your source code is bound at compile time to the signature of a specific static method provided by a specific class.

So, if countHowMany is a static method implemented by lots of classes, then you find that you have to do things like this:

  int total = Class1.countHowMany() + Class2.countHowMany() + ...

... and something like this:

  for ( Class <? extends ICountMyself> currentClass : listOfUnitClasses )

simply won't work, because the class Class does not expose any of the methods of ICountMyself. (Well, you could use reflection ... but that is nasty. It is "bad design" smell to use reflection like this.)


A small improvement on your current approach would be to make countHowMany() an instance method instead of a static method. That would allow you to declare all of your classes as extends ICountMyself and then invoke the countHowMany on any instance of any of those classes. The method can be implemented as returning or updating the appropriate (class specific) static variable.

But that is still bad design smell.


The proper object-oriented way to do this is to replace the static variables. Instead, declare a class or classes that represent "collections that may contain zerklings"; e.g. "forces". Make the countHowMany method an instance method of a "force" object ... or whatever ... and have it either return the value of an instance variable associated with the collection, or calculate the value by examining all of the current elements of the "force".

3 Comments

Would you still say that the static member variable is a bad idea in light of the sprite idea? Basically, do I say that the class responsible for drawing units to the screen should just know about how to draw all units, or would it be worth a little pain in using static member variables so that each individual unit can draw itself? I am tempted to think that the latter feels like it more closely adheres to object oriented design, if it weren't for the static interface method issue.
Though I can see why this is close to "abuse" of static member variables. Difficulties arise when you want to access them from the outside, but don't know in advance which ones to use. The reason I thought of a static member variable at all is from an old Deitel how-to-program book. Inside was an example of a Martian game class, the behavior of which on the board depended on how many existed. They recommend this scenario as one to use a static integer to maintain the count.
It is obviously a matter of opinion, but yes I would say that it is still a bad idea. The justification for using a static for each sprite seems to boil down to the cost of a hashmap lookup. But there are ways of dealing with that: 1) cache the lookup result in instance fields, or 2) use a Dependency Injection mechanism to populate the sprite references.
0

Whenever you find yourself willing to use a static method in an interface to have it implemented in other classes, the Java way would be to use a new generic interface implementing the method.

For your use case, let call it a Bunch, and assume all your soldiers and beasties classes all implement Countable

interface Bunch<T extends Countable> {
    void add(T elt);
    void remove(T elt);
    int count();
}

You could also define an abstract class of some methods can be fully implemented in a generic way :

class AbstractBunch<T extends Countable> implements Bunch<T> {
    private List<T> list;

    @Override
    int count() {
        return list.size();
    }
    ...
}

And then you define you concrete classes extending AbstractBunch :

class ZerblingBunch extends AbstractBunch<Zerbling> {
    ...
}

This pattern allows even you to have different bunches in the same application.

2 Comments

I will definitely have to look into generic interfaces and see what all I can do with them. One question, though. If I understand this correctly, there will be some other class in which all of my bunch objects reside. If that is so, then I would end up modifying two classes when I add a new unit type. For example, a new Metalisk class would require the unit class itself, plus a change to include a new concrete Metalisk bunch. Is that the case here?
@RobH More exactly to add the Metalisk class, you will add the class itself (a minimum...) and a concrete class implementing Bunch<Metalisk>, or better extending AbstractBunch<Metalisk> provided you put there all common methods and override only for Metalisk particurlarities.
0

You should take advantage of Java Generics. You have some number of Zerklings instantiated, which derive from Beastie that in turn derive from MilitaryUnit. Use a java.util.Set to hold lists of those units: after all, every unit must be unique, and so should only be in your Set once. The Set will enforce this.

Thus, you might have:

Set<Zerkling> zerklings = new HashSet<Zerkling>();
//... elsewhere in code
zerklings.size();//Number of zerklings you have.

Note that a single Zerkling can be a part of many sets:

Set<Zerkling> allZerklings = new HashSet<Zerkling>();
Set<Zerkling> deadZerklings = new HashSet<Zerkling>();
Zerkling bob = new Zerkling();
liveZerklings.add(bob);
// 1 zerkling in 'all', 0 in 'dead'
// Lets kill bob!
bob.kill();
deadZerklings.add(bob);//really you'd want to do this inside the kill() method
// 1 zerkling in 'all', 1 in 'dead'

The issue you run across with using a static method is that you can't be clear who or when a caller is accessing that method. This makes multithreading at the very least difficult to manage (and if you're doing an actual game, you're likely to have multiple threads running if only to async UI). Consider the following:

* Call to static method to set value to x
* Mid-call thread is suspended and another thread picks up
* That thread sets value to y
* First call completes, no one knows if they have the right value.

Remember that static class fields can be modified by anyone who has that class. Even if that class isn't being used actively to represent a 'live' Zerkling, such as if you are using it to represent a zerkling growing in a zerkling hive, or in your help menu, or anywhere else that class might be summoned.

1 Comment

I didn't even take multiple threads into consideration. That's a good call. For my original problem, the fields could be considered read-only after being initially set, but I can see how this would be a potential problem elsewhere.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.