Reputation: 11
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
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
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