I have the following class structure:
DataStore classes:
PStore
: public abstract class PStore ...
CStore1
and CStore2
CStore1.getInstance(Id)
and CStore2.getInstance(Id)
Worker classes:
public abstract class PWork...
CWork1
and CWork2
Current situation:
Class CWork1
implemented an inner class with the following code accessing the Store:
protected class fListener implements ActionListener {
public void actionPerformed(ActionEvent ae) {
CStore1.getInstance(Id).someMethod();
# NOTE: someMethod() is implemented in CStore2 as well
}
}
I need to implement the same fListener
class in CWork2
Being a good little software developer, instead of simply copy/pasting fListener
from CWork1
to CWork2
class and then changing CStore1
to CStore2
in its code, I decided like an idiot to migrate it to a parent class.
What I tried to do:
Create an abstract method in PStore
called getStoreInstance(int Id)
: public abstract PStore getStoreInstance(int Id);
Implement that method in CStore1
as public PStore getStoreInstance(int Id) { return CStore1.getInstance(Id); }
So far, so good. It compiled all 3 Store classes.
Copy the fListener code from PWork
to CWork1
class
Obviously, the compiler complained that it does not know anything about CStore1 class and its method getStoreInstance()
Now, I decided to simply call the newly created getStoreInstance()
:
Old code: CStore1.getInstance(Id).someMethod();
New code: PStore.getStoreInstance(Id).someMethod();
Compiler complaint: "Cannot make a static reference to the non-static method getStoreInstance(Id) from the type PStore".
The only "fix" proposed by Eclipse was to make getStoreInstance() method static, but THAT didn't work either:
When I added a static
modifier to the abstract classes's declaration of the method: public static abstract PStore getStoreInstance(int Id);
- the compiler complained that "The abstract method getStoreInstance in type PStore can only set a visibility modifier, one of public or protected"
When I tried to make the method non-abstract: public static PStore getStoreInstance(int Id);
it complained that the method needed a body (quite sensibly)
When I tried to add a body, it required me to return PStore object... BUT!!!! My abstract class PStore has no constructore, so there's no way I can return PStore object!!!
Am I approaching the problem correctly?
If not, how should I approach it?
If I am, then how can I resolve the original complaint about "Cannot make a static reference to the non-static method", in light of the fact that the abstract class isn't letting me make that method static?
The way it looks to me, you have two class hierarchies that are isomorphic (if I'm using the right term) and there is a relationship between the corresponding classes:
PStore PWork
/ \ / \
/ \ / \
CStore1 CStore2 CWork1 CWork2
^ ^ ^ ^
| | | |
|---------+--------------| |
| |
|---------------------|
But I don't think there's a built-in way to express this kind of relationship in Java.
Somehow, you're going to have to do something that makes those relationships explicit. I.e. there will need to be something in CWork1
that refers to CStore1
, and something in CWork2
that refers to CStore2
, or else some kind of list or map that associates them.
There's probably a design pattern that addresses this structure, but I can't think of it right now. So off the top of my head, here are a couple possible solutions (neither of which uses reflection):
Put the abstract getStoreInstance
method you defined in PWork
instead of PStore
. In CWork1
, override it with a method that calls CStore1.getInstance
, and similarly in CWork2
. Then the common fListener
actionPerformed
code would call getStoreInstance(Id).someMethod()
, with no class name, which would work on the current PWork
instance. You would still have some "duplicated" code (since you'd have to implement getStoreInstance
in both CWork
classes), but it would be kept to a minimum.
Set up a map. This compiles (Java 8), but I haven't tested it:
class PWork {
private static Map<Class<? extends PWork>,IntFunction<PStore>> storeMap;
static {
storeMap = new HashMap<>();
storeMap.put(CWork1.class, CStore1::getInstance);
storeMap.put(CWork2.class, CStore2::getInstance);
}
protected PStore getStoreInstance(int Id) {
return storeMap.get(getClass()).apply(Id);
}
protected class fListener implements ActionListener {
public void actionPerformed(ActionEvent ae) {
int Id = ???; // I'm assuming Id is computed from ae somehow??
getStoreInstance(Id).someMethod();
}
}
}
Now getStoreInstance
looks in the map, using the current PWork
object's class (CWork1
or CWork2
) as a key, to figure out which getInstance
static method to call.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With