Paul
Paul

Reputation: 11

Design pattern needed for enforcing static methods

Okay, I want to start off my question with an example of what I'd basically like to do, though it's not working this way.

I want to have an interface IDog that enforces its implementations to have some methods. I also want an superclass AbstractDog implements IDog to give basic attributes and methods to all Dog classes. Then I want to have Subclasses like Poodle extends AbstractDog. My problem here are static methods - I basically want each subclass of AbstractDog to have a different static method but I want to be able to enforce this method from IDog.

So my naïve (and wrong) implementation would be:

public interface IDog {

    String getName(); // every dog instance should be able to call name
    static String getDescription(); // every dog class should be able to get its description

}

public abstract class AbstractDog implements IDog {

    private String name; // every dog instance will have this

    public AbstractDog(String name) {
        this.name = name;
    }

    @Override
    public String getName() {
        return this.name; // every dog instance can call this
    }

}

public class Poodle extends AbstractDog {

    private static String description = "It's a poodle!"; // all Poodles have the same description

    public Poodle(String name) {
        super(name);
    }

    @Override // from IDog
    public static String getDescription() {
        return description;
    } 

}

Now, as I said, this is not correct because the AbstractDog class would need a static abstract method getDescription() and IDog needs an implementation of its method and it can't be overridden.

I want to know, if there is a Design pattern which matches my problem: enforcing a set of classes (which could or should have an intermediate superclass) to implement a (different!) static method.

One possibility I have discovered, but I'm not sure if it may be useful or even adequate, would be the use of an enum DogType and then just having a class Dog with a DogType attribute:

public enum DogType {

    Poodle("This is a poodle."), Havanese("This is a Havanese.)";

    private String description;

    private DogType(String description) {
        this.description = description;
    }

    public String getDescription() {
        return this.description;
    }
}

public class Dog {

    private String name;
    private DogType dogType;

    public Dog(String name, DogType dogType) {
        this.name = name;
        this.dogType = dogType;
    }

    public String getName() {
        return this.name;
    }

    public String getDescription {
        return this.dogType.getDescription();
    }
}

However, this "workaround" loses an ability over my initial idea: I now can't additional functionalities to only one dog class like an instance method void prance() which should only be accessible to Poodle.

Many topics regarding similar questions have refered to the Factory pattern, but I'm not sure how it fits my problem because I don't necessarily need a constructing method. And as the number of dog races rises my code would become very confusing I think. Or maybe I just didn't get how the Factory should be used correctly in my case.

Upvotes: 1

Views: 82

Answers (2)

Tejas Unnikrishnan
Tejas Unnikrishnan

Reputation: 508

Interfaces are enforced behaviours. Classes are used to specify properties. Static methods get hidden. They are not over-ridden by subclasses. So if you have static methods in your subclasses, but your object reference is of supertype class, then your static method from superclass is invoked. This is class Method hiding, happens with static methods.

I want to know, if there is a Design pattern which matches my problem: enforcing a set of classes (which could or should have an intermediate superclass) to implement a (different!) static method.

Sorry. Static methods and inheritance don't go hand in hand.

I now can't additional functionalities to only one dog class like an instance method void prance() which should only be accessible to Poodle.

You could introduce a interface Prancable with method void prance().

public interface Prancable{
      void prance();
}
public class Poodle extends Dog implements Prancable{
      @Override
      public void prance(){
           System.out.println("My Poodle can prance.");
      }
}

You can proceed in this manner for specific methods that add behaviour to different dog breeds.

Upvotes: 3

simba
simba

Reputation: 37

This is a code smell, there is likely a better way to do it.

If the static method will always return the same thing for all objects of the class, you should just make it a regular get method.

@Override \\ from IDog
public String getDescription() {
    return "This is a poodle";
} 

If the static variable may be changed then make a new object that holds this class-wide state and give it to each class in the constructor.

ex.

// StringState is a new class that holds a string and has a set and get method
StringState desc = new StringState("original description");
IDog dog1 = new Poodle(desc);
IDog dog2 = new Poodle(desc);
// prints original description
System.out.Println(dog1.getDescription());
System.out.Println(dog2.getDescription());

desc.set("New description");
// prints new description, since both objects share the same
// StringState,changing it here changes it in all of them.
System.out.Println(dog1.getDescription());
System.out.Println(dog2.getDescription());

Upvotes: 2

Related Questions