Make super class use the Enum used by the child class - java

I have
public enum BaseActions implements Actions{
STAND (0,0,0),
TURN (1,1,1);
//other stuff
}
public enum CoolActions implements Actions{
STAND (0,2,3),
TURN(1,6,9);
//other stuff
}
public enum LooserActions implements Actions{
STAND (0,-2,-3),
TURN(1,-6,-9);
//other stuff
}
public interface Actions {
//interface methods
}
class A {
Actions mCurrentAction;
protected void notifyNewAction(final Actions pAction, final Directions pDirection){
//body of the method
}
public void doStuff(final Actions pAction) {
if(pAction.getMyId() > 0)
notifyNewAction(BaseActions.STAND, myDirection);
else
notifyNewAction(BaseActions.TURN, myDirection);
}
}
class B extends A{
public void doMyStuff() {
doStuff(CoolActions.STAND);
}
}
class C extends A{
public void doMyStuff() {
doStuff(LooserActions.STAND);
}
}
i would like to make A use CoolActions when doStuff is called from B and LooserActions when called from C.
One of the ways i think i can do it is to use generics, and then in B and C use
doStuff<CoolActions>(CoolActions.STAND)
and have in A
public void doStuff<T extends EnumActions&Actions>(final Actions pAction) {
if(pAction.getMyId() > 0)
notifyNewAction(T.STAND, myDirection);
else
notifyNewAction(T.TURN, myDirection);
}
where EnumActions is a base enum that just contains the declaration of the enum's elements, and nothing more, something like an interface for enums, but enums can't extend another class since they already extends Enum, and an interface can't provide what i mean.
Another way would be to make the enums implements a EnumActions interface that has
public interface EnumActions {
public <T> T getStand();
public <T> T getTurn();
}
and have
class A {
Actions mCurrentAction;
protected void notifyNewAction(final Actions pAction, final Directions pDirection){
//body of the method
}
public <T implements EnumActions> void doStuff(final Actions pAction) {
if(pAction.getMyId() > 0)
notifyNewAction(T.getStand(), myDirection);
else
notifyNewAction(T.getTrun(), myDirection);
}
}
and
public enum CoolActions implements Actions, EnumActions{
STAND (0,2,3),
TURN(1,6,9);
public CoolActions getStand();
public CoolActions getTurn();
//other stuff
}
class B extends A{
public void doMyStuff() {
doStuff<CoolActions>(CoolActions.STAND);
}
}
But 1)i don't know if it would work 2) I lose the advanteges of using enums 3) this seams a really bad way to handle this 4) i would have to write a lot( X enum fields per Y different enums). I changed from static final fields to enum to improve readability and order, and this seams to make things even harder.
Am i designing this in the wrong way? How can i handle this?
Is there a preferred way to solve this problem?
Thanks

It seems like enums add nothing and are not going to do what you want. Maybe you should just use a normal class hierarchy - make BaseActions, CoolActions and LooserActions just classes that implement Actions and STAND and TURN methods in those classes.

it's ugly, but it may do what you want:
interface Actions {
int getMyId();
}
enum BaseActions implements Actions {
STAND(0, 0, 0), TURN(1, 1, 1);
BaseActions(int x, int y, int z) {}
#Override public int getMyId() {
return 0;
}
}
enum CoolActions implements Actions {
STAND(0, 2, 3), TURN(1, 6, 9);
CoolActions(int x, int y, int z) {}
#Override public int getMyId() {
return 0;
}
}
enum LooserActions implements Actions {
STAND(0, -2, -3), TURN(1, -6, -9);
LooserActions(int x, int y, int z) {}
#Override public int getMyId() {
return 0;
}
}
class Directions {}
class A {
Actions mCurrentAction;
protected void notifyNewAction(final Actions pAction, final Directions pDirection) {
System.out.println(pAction+" "+pAction.getClass());
}
public void doStuff(final Actions pAction) {
Directions myDirection = null;
Enum e=(Enum)pAction;
if(e instanceof CoolActions)
e=CoolActions.valueOf(e.name());
else if(e instanceof LooserActions)
e=LooserActions.valueOf(e.name());
if (pAction.getMyId() > 0) notifyNewAction((Actions)e, myDirection);
else
notifyNewAction((Actions)e, myDirection);
}
}
class B extends A {
public void doMyStuff() {
doStuff(CoolActions.STAND);
}
}
class C extends A {
public void doMyStuff() {
doStuff(LooserActions.STAND);
}
}
public class Main {
public static void main(String[] args) {
A a = new A();
a.doStuff(BaseActions.STAND);
B b = new B();
b.doMyStuff();
C c = new C();
c.doMyStuff();
}
}

Related

java mutant design pattern and compiler error 'Interface' cannot be inherited with different type arguments 'TypeA' and 'TypeB'

I am way over thinking this: What I am trying to do is [hopefully not reinvent the wheel and] come up w/ a [Android] Java eventing mechanism that allows subclasses to pre-define an arbitrary set of "features" with getters and setters that fire individual callbacks.
I think I am fusioning some combination of Command, Visitor, Decorator, Facade and Observer patterns here, and confusing myself along the way.
I have been programming for well over 20 years, but I feel like a n00b on this fairly simple problem! :(
I have searched SO for the compiler error and read many of the results, but I still haven't found a solution that works for me.
(How to make a Java class that implements one interface with two generic types? seems to be the most relevant one that I have found, but I also want to generically get the values and fire events to callbacks when they are set).
First, let the below mostly valid code speak for itself...
interface IFeature
{
}
interface IFeatureCallbacks<T extends IFeature>
{
boolean onChanged(Feature<T> c);
}
public static class Feature<T extends IFeature>
{
private Set<IFeatureCallbacks<T>> listeners = new LinkedHashSet<>();
public void addListener(IFeatureCallbacks<T> listener)
{
listeners.add(listener);
}
public void removeListener(IFeatureCallbacks<T> listener)
{
listeners.remove(listener);
}
protected void onChanged()
{
for (IFeatureCallbacks<T> listener : listeners)
{
listener.onChanged(this);
}
}
}
//
interface IFeatureA
extends IFeature
{
int getA();
}
interface IFeatureACallbacks
extends IFeatureCallbacks<IFeatureA>
{
}
public static class FeatureA
extends Feature<IFeatureA>
implements IFeatureA
{
private int a;
public void setA(int value)
{
a = value;
onChanged();
}
#Override
public int getA()
{
return a;
}
}
//
interface IFeatureB
extends IFeature
{
boolean getB();
}
interface IFeatureBCallbacks
extends IFeatureCallbacks<IFeatureB>
{
}
public static class FeatureB
extends Feature<IFeatureB>
implements IFeatureB
{
private boolean b;
public void setB(boolean value)
{
b = value;
onChanged();
}
#Override
public boolean getB()
{
return b;
}
}
//
interface IDeviceWithFeatureA
extends IFeatureA
{
}
interface IDeviceWithFeatureACallbacks
extends IFeatureACallbacks
{
}
public static class DeviceWithFeatureA
extends Feature<IDeviceWithFeatureA>
implements IDeviceWithFeatureA
{
FeatureA a = new FeatureA();
public void addListener(IDeviceWithFeatureACallbacks listener)
{
a.addListener(listener);
}
public void setA(int value)
{
a.setA(value);
}
#Override
public int getA()
{
return a.getA();
}
}
//
interface IDeviceWithFeatureB
extends IFeatureB
{
}
interface IDeviceWithFeatureBCallbacks
extends IFeatureBCallbacks
{
}
public static class DeviceWithFeatureAB
extends Feature<IDeviceWithFeatureB>
implements IDeviceWithFeatureB
{
FeatureB b = new FeatureB();
public void addListener(IDeviceWithFeatureBCallbacks listener)
{
b.addListener(listener);
}
public void setB(boolean value)
{
b.setB(value);
}
#Override
public boolean getB()
{
return b.getB();
}
}
The above code seems to work fine, albeit something about it smells a bit off.
The problem is when I try to do this:
interface IDeviceWithFeatureAAndFeatureB
extends IFeatureA, IFeatureB
{
}
/*
Compiler error:
'IFeatureCallbacks' cannot be inherited with different type arguments 'IFeatureA' and 'IFeatureB'
*/
interface IDeviceWithFeatureAAndFeatureBCallbacks
extends IFeatureACallbacks, IFeatureBCallbacks
{
}
public static class DeviceWithFeatureAB
extends Feature<IDeviceWithFeatureAAndFeatureB>
implements IDeviceWithFeatureAAndFeatureB
{
FeatureA a = new FeatureA();
FeatureB b = new FeatureB();
public void addListener(IDeviceWithFeatureAAndFeatureBCallbacks listener)
{
a.addListener(listener);
b.addListener(listener);
}
public void setA(int value)
{
a.setA(value);
}
#Override
public int getA()
{
return a.getA();
}
public void setB(boolean value)
{
b.setB(value);
}
#Override
public boolean getB()
{
return b.getB();
}
}
I am less interested in trying to figure out how to make what I am trying to do compilable, and I am more interested in what about my abuse of a pattern is way off base so that I can re-write it to be both simpler and compile.
You are abusing the basic "pattern" of OOP -- inheritance. The adage is that "favor composition over inheritance". Think in terms of "contains", instead of "is-a".
Take Zoo for example. A zoo is just a bunch of animals, right? So naturally, we may want to declare Zoo as subtype of Set<Animal>. Perhaps even have class Zoo extends HashSet<Animal>.
However, that is likely a wrong design. A zoo is actually a lot of things. It contains a set of animals, sure; but it also contains a set of people (as workers, not exhibits (although...) ). So it's better to
class Zoo
Set<Animal> animals(){ ... }
Set<Person> workers(){ ... }
Anywhere we need to treat a zoo as a set of animals, just use zoo.animals(); think of it as a type cast, or projection. We don't need inheritance here.
In your design, you have too many types; what's worse, too many type relationships. It seems that you simply need one generic class that reads/writes value of T, and contains listeners of T
class Feature<T>
T value;
// getter
// setter
Set<ChangeListener<T>> listeners;
interface ChangeListener<T>
void onChange(T oldValue, T newValue)
A device contains a bunch of features
class SomeDevice
Feature<Integer> featureA = new Feature<>();
Feature<Boolean> featureB = new Feature<>();
That's it. You can operate on feature A of the device by operating on itsfeatureA.

Java extends generic prototype

I have few classes that implements some interface. Now I want to create new class, which can extend one of them, based on runtime calculation while using interfaces methods. Let's talk in code:
public interface Interface {
public void doSomething();
}
public class A implements Interface {
#Override
public void doSomething() {
System.out.println("hello");
}
}
public class B implements Interface {
#Override
public void doSomething() {
System.out.println("hi");
}
}
These are existing classes, so now I need to do something like this (which is not working of course):
public class C<T extends Interface> extends T {
public void doSomethingElse() {
this.doSomething();
}
public static void main(String[] args) {
C c;
if(isSomethingLoaded) {
c = new C<A>();
} else {
c = new C<B>();
}
c.doSomethingElse();
}
}
Is it possible somehow, except the way that I pass argument Interface other to C's constructor and store to class property..?
A class cannot extend from its type parameter.
Use composition instead of inheritance:
public class C<T extends Interface> {
private final T foo;
public C(T foo){
this.foo = foo;
}
public void doSomethingElse() {
foo.doSomething();
}
public static void main(String[] args) {
C<?> c;
if(isSomethingLoaded) {
c = new C<>(new A());
} else {
c = new C<>(new B());
}
c.doSomethingElse();
}
}
You might even not need the type parameter here, but just use the interface type as argument/ member type.
I think it's situations like this which show why we have the rule of favouring composition over inheritance. Consider this solution using composition:
public class Test {
public interface Interface {
void doSomething();
}
public static class A implements Interface {
#Override
public void doSomething() {
System.out.println("Doing A");
}
}
public static class B implements Interface {
#Override
public void doSomething() {
System.out.println("Doing B");
}
}
public static class C implements Interface {
private Interface composedWith;
public C(Interface i) {
this.composedWith = i;
}
#Override
public void doSomething() {
this.composedWith.doSomething();
}
}
public static void main(String[] args) {
C c;
if(isSomethingLoaded) {
c = new C(new A());
} else {
c = new C(new B());
}
c.doSomething();
}
}
Personally, I feel this is a clearer and move flexible way of achieving what you are trying to do.

what scenario should abstract class used in java?

I am not familiar in OOPS concept, I have doubt while using abstract class, please clear my doubt.
I have four classes ex: class A, class B, class C and Main class.
class A, B and C contains same method name but the method definition is different
the implementation is like,
class A
{
getValue();
setValue();
}
class B
{
getValue();
setValue();
}
class C
{
getValue();
setValue();
}
In the Main class, I need to call setValue() or getValue(), it can be any of the above three class, how to implement this scenario?
class Main
{
Main()
{}
x.setValue();
x.getValue();
}
where x can be Object for either class A or class B or class C.
The abstract class defines, what methods are available. In your case, this would be
abstract class YourAbstractClass {
abstract public int getValue();
abstract public void setValue(int i);
}
Now your classes A, B and C can inherit this class.
class A extends YourAbstractClass {
public int getValue() { return 23; }
public void setValue(int i) { /* set i */ }
}
class B extends YourAbstractClass {
public int getValue() { return -3; }
public void setValue(int i) { /* set i */ }
}
class C extends YourAbstractClass {
public int getValue() { return 3; }
public void setValue(int i) { /* set i */ }
}
In your main class you can use it the like this:
public class Execution {
public static void main(String[] args) {
YourAbstractClass o = new A();
o.getValue();
o.setValue(3);
}
}
In your particular case you don't need an abstract class but an interface:
public interface I {
Object getValue();
Object setValue();
}
Then your 3 classes A, B and C must implement this interface:
class A implements I {
Object getValue() {...}
void setValue( someParam) {...}
}
class B implements I {
Object getValue() {...}
void setValue( someParam) {...}
}
class C implements I {
Object getValue() {...}
void setValue( someParam) {...}
}
And finally in your main class:
class Main
{
Main()
{
I x = callWhateverYouWantReturningABOrC();
x.setValue();
x.getValue();
}
You could implement that in a couple of ways:
public interface Valuable {
void getValue();
void setValue();
}
class A implements Valuable {
getValue() { ... }
setValue() { ... }
}
class B implements Valuable {
getValue() { ... }
setValue() { ... }
}
class C implements Valuable {
getValue() { ... }
setValue() { ... }
}
Or ...
abstract class Valuable {
void getValue() { ... }
void setValue() { ... }
}
class A extends Valuable {
}
class B extends Valuable {
}
class C extends Valuable {
}
Or ... a hybrid where you both interfaces and abstract classes.
Which is more appropriate depends on a number of things, including whether the method implementations are the same or not. If they are, then the abstract class eliminates some duplicate code.
If I got your question right, you want to create an interface:
interface I {
int getValue();
void setValue(int x);
}
and your classes will implement it:
class A implements I {..};
class B implements I {..};
class C implements I {..};
Then in your Main class you can have method, which doesn't have to know which concrete implementation of I the x variable is (wheather A, B or C) and it can call it's methods:
{
I x = new A(); // or new B() or C()
x.setValue(1);
x.getValue();
}
You can make Main an interface.
interface is a pure abstract class.
public interface Main {
void setValue();
void getValue();
}
Then make A, B, and C classes to implement the Main interface
public class A implements Main {
#Override
public void setValue() {
...
}
#Override
public void getValue() {
...
}
}
public class B implements Main {
#Override
public void setValue() {
...
}
#Override
public void getValue() {
...
}
}
public class C implements Main {
#Override
public void setValue() {
...
}
#Override
public void getValue() {
...
}
}

How to use Google Guice to inject a dependancy

I've gone through the user guide and everything but yet I still don't understand exactly how to modify existing code to use Google Guice when trying to inject dependencies. So to make it easier I created this simple example and if someone could explain with this simple example I would really appreciate it!
Say I have a
public Class A {
private int count = 0;
public A() {
}
public int getCount() {
return count;
}
public void setCount(int newCount) {
this.count = newCount;
}
}
and another class
public Class B {
private A objectA;
public B() {
objectA = new A();
}
public void messWithCount() {
int tempCount = objectA.getCount();
objectA.setCount(tempCount+1);
}
}
So basically my question is: how would I go about using Google Guice to extract creation of objectA in the constructor B() and instead inject it as a dependency in Class B where it would amount to something like
#Inject
public B() {
}
and how would I actually inject an instance of A into it?
First, B should not be bound to class A but rather use an interface (such as AInterface).
The main point of Guice is to bind different implementations of the same interface, without being tied to some class.
So let's assume Class A implements AInterface
interface AInterface {
public int getCount();
public void setCount(int newCount);
}
class A implements AInterface {
private int count = 0;
public A() {
System.out.println("done!");
}
#Override
public int getCount() {
return count;
}
#Override
public void setCount(int newCount) {
this.count = newCount;
}
}
Now you tell it to inject your variable:
class B {
#Inject
private AInterface objectA;
public B() {}
public void messWithCount() {
int tempCount = objectA.getCount();
objectA.setCount(tempCount + 1);
}
}
I removed the static modifier, but if you insist in having it static you'd need to bind using requestStaticInjection instead
you tie the implementation A to the interface AInterface in a special class called module:
class SimpleModule extends AbstractModule {
#Override
protected void configure() {
bind(AInterface.class).to(A.class);
}
}
Now you ask Guice to generate B for you.
public class Temptemp {
public static void main(String[] args) {
Injector i = Guice.createInjector(new SimpleModule());
B b = i.getInstance(B.class);
}
}
You can inject A into B in two ways, actually many ways but with in the context of your question I would say two.
Make sure both A and B class is configured in a Module. Follow condit example code/class that extends AbstractModule.
1.a
class B {
#Inject
private A a;
public B() {
}
}
1.b
class B {
private A a;
#Inject
public B(A a) {
this.a = a;
}
}
These both works fine but 1.b is useful if you want to write test for class B. Where your test will mock A class and creates instance of B. like
class BTest {
#Test
public void testSomeMethodOfB() {
A a = mock(A.class);
B b = new B(a);
//run some test on b;
}
}
Here's an example based on what you already have:
public class GuiceExample {
static class A {
private int count = 0;
public A() {}
public int getCount() {
return count;
}
public void setCount(int newCount) {
this.count = newCount;
}
}
static class B {
#Inject
private static A objectA;
public B() {}
public void messWithCount() {
int tempCount = objectA.getCount();
objectA.setCount(tempCount+1);
}
}
static class Module extends AbstractModule {
#Override
protected void configure() {
requestStaticInjection(B.class);
}
}
#Test
public void test() {
Injector i = Guice.createInjector(new Module());
B b = i.getInstance(B.class);
//Do something with b
}
}
Note, though, that static injection is not preferred. You could make A non static and Guice will still inject the field. The even more "correct" way would be to drop the requestStaticInjection call and add A as construction argument like:
static class B {
private A objectA;
#Inject
public B(A objectA) {
this.objectA = objectA;
}
...
}

Java: If-else instanceof extended classes

I have an abstract class X and some classes who extend this class, call them A, B and C.
In some other class Y I have a few methodcalls that depend on the type of the class. The if-else statement looks like this:
public class Y implements InterfaceY {
public Y(){
}
public String doStuff (X x, Boolean flag) {
String s = "";
if (x instanceof A) {
doStuff((A) x));
} else if (x instanceof B) {
doStuff((B) x));
} else if (x instanceof C) {
doStuff((C) x, flag);
} else {
throw new Exeption();
}
return s;
private String doStuff(A a) {
return "";
}
private String doStuff(B b) {
return "";
}
private String doStuff(C c, Boolean flag) {
return "";
}
}
Note that all methods have the same name (doStuff()) but depending on the class (and sometimes flag) call a different method implementation of that method. Of course this looks horrible and gets immensely complicated once the classed that are extended from X increase.
Is there any way that I can somehow create an intermediate Interface that (or something else) that takes care of the majority (or all) of the if-else statements?
First take these methods out of here, and put them in the A, B and C class respectively, implementing the X interface.
private String doStuff(A a) {
return "";
}
private String doStuff(B b) {
return "";
}
private String doStuff(C c, Boolean flag) {
return "";
}
Then:
if (x instanceof A) {
doStuff((A) x));
} else if (x instanceof B) {
doStuff((B) x));
} else if (x instanceof C) {
doStuff((C) x, flag);
can just be x.doStuff(); (you don't even have to pass the A, B, C because that will be this inside the method. The flag you'll have to mess around with depending more specifically on your code. for example, the other 2 doStuff methods could accept the flag as well, but just ignore it)
What about implementing a Handler interface then map it by supported type:
public interface Handler<T extends X>{
Class<T> supportedClass;
void doStuff(T value, Object...args);
}
public class Y implements InterfaceY {
private Map<Class<?>, Handler<?>> handlers;
public Y(List<Handler<?>> handlers){
// populate map
}
public void process(X value){
handler.get(value.getClass).doStuff(X, ...);
// you would have to figure out how to determine when other values are needed
}
}
What about some double dispatch?
class X {
public String letYdoStuff(Y y, Boolean flag) {
return y.doStuff(this, flag);
}
public static void main(String [] args) {
//X x = new A();
X x = new B();
Y y = new Y();
y.doStuff(x, false);
}
public X getThis() {
return this;
}
}
class A extends X {
public String letYdoStuff(Y y, Boolean flag) {
return y.doStuff(this, flag);
}
}
class B extends X {
public String letYdoStuff(Y y, Boolean flag) {
return y.doStuff(this, flag);
}
}
class C extends X {
public String letYdoStuff(Y y, Boolean flag) {
return y.doStuff(this, flag);
}
}
class Y {
public Y(){
}
public String doStuff (X x, Boolean flag) {
String s = "";
return x.letYdoStuff(this, flag);
}
public String doStuff(A a, Boolean flag) {
System.out.println("in A");
return "";
}
public String doStuff(B b, Boolean flag) {
System.out.println("in B");
return "";
}
public String doStuff(C c, Boolean flag) {
System.out.println("in C");
return "";
}
}
APPROACH 1
Use the state pattern. It takes care of your problem and eliminates the ifs and elses.
Here is the java example.
The state pattern delegates the methods calls to objects that implement the same interface but with different behaviour.
State pattern example:
public class StatePatternExample {
public static void main(String[] args) {
Girlfriend anna = new Girlfriend();
// OUTPUT
anna.kiss(); // *happy*
anna.greet(); // Hey, honey!
anna.provoke(); // :#
anna.greet(); // Leave me alone!
anna.kiss(); // ...
anna.greet(); // Hey, honey!
}
}
interface GirlfriendInteraction extends GirlfriendMood {
public void changeMood(GirlfriendMood mood);
}
class Girlfriend implements GirlfriendInteraction {
private GirlfriendMood mood = new Normal(this);
public void provoke() {
mood.provoke();
}
public void kiss() {
mood.kiss();
}
public void greet() {
mood.greet();
}
public void changeMood(GirlfriendMood mood) {
this.mood = mood;
}
}
interface GirlfriendMood {
public void provoke();
public void kiss();
public void greet();
}
class Angry implements GirlfriendMood {
private final GirlfriendInteraction context;
Angry(GirlfriendInteraction context) { // more parameters, flags, etc. possible
this.context = context;
}
public void provoke() {
System.out.println("I hate you!");
}
public void kiss() {
System.out.println("...");
context.changeMood(new Normal(context));
}
public void greet() {
System.out.println("Leave me alone!");
}
}
class Normal implements GirlfriendMood {
private final GirlfriendInteraction context;
Normal(GirlfriendInteraction context) {
this.context = context;
}
public void provoke() {
System.out.println(":#");
context.changeMood(new Angry(context));
}
public void kiss() {
System.out.println("*happy*");
}
public void greet() {
System.out.println("Hey, honey!");
}
}
As you can see, the class Girlfriend has no ifs and elses. It looks pretty clean.
The class Girlfriend corresponds to your abstract class X, the classes Normal and Angry correspond to A, B and C.
Your class Y then directly delegates to X without checking any cases.
APPROACH 2
Use the command pattern. You could then hand over a command object to Ys doStuff() method and just execute it.
This can be a difficult problem. I think Cruncher's solution, add
doStuff to X and override it in A, B, C, is the simplest and
best solution when it's appropriate. However, it isn't always
appropriate, because of the Single responsibility
principle.
(I think that's the correct term. My apologies if I get some
terminology wrong, I'm not entirely up-to-date on all of the terms.)
The idea is that you shouldn't necessarily doStuff to X if it has
nothing to do with the purpose of X. If X and Y are part of the
same "team", i.e. they've been both set up to serve the purpose of one
particular application, then it's probably OK.
But suppose you have an abstract Shape class that has subclasses
Circle, Square, Undecagon, RandomBlob, etc. There will be
some methods that belong in the Shape class that would be useful to
any application that uses the Shape class. But now say you are
writing a game that uses some of those shapes, and you want a
polymorphic operation that determines what happens when the shape gets
eaten by a flying monkey. You wouldn't want to add an abstract
computeEatenByFlyingMonkey method to your Shape class, even if the
class were your own creation and not in someone else's library,
because that would be just too specific for a class that could be
generally used for other purposes than this one game.
I can think of a couple ways to approach this.
If it's not appropriate (or not possible) to add doStuff to X, but
if A, B, and C are more closely connected to your application so
that adding doStuff to them is appropriate, you can add another
class:
public abstract class XWithStuff extends X {
// repeat any constructors in X, making them all be just
// calls to super(...)
public abstract void doStuff (Boolean flag);
}
public class A extends XWithStuff {
#Override
public void doStuff (Boolean flag) { ... }
}
and so on for every other class. (XWithStuff is just an example
name; in real life, a name that contains both "X" and some reference
to the application or purpose is probably better.) (P.S. I don't know
why you're using Boolean instead of boolean but I'm leaving it
that way in case there's a good reason.)
If it's also not appropriate or not possible to add doStuff to A,
B, and C, here's a possible solution:
public interface StuffInterface {
public void doStuff (Boolean flag);
}
public class AWithStuff extends A implements StuffInterface {
#Override
public void doStuff (Boolean flag) { ... }
}
and then in your program create objects of class AWithStuff instead
of A, etc. To call doStuff on an X:
void doStuff (X x, Boolean flag) {
if (x instanceof StuffInterface) {
((StuffInterface) x).doStuff (flag);
} else {
throw new IllegalArgumentException ();
}
}
If that's not an option and you have to deal directly with A, B,
etc., and you can't add doStuff to those classes, then any solution
will be a bit hacky. If you don't want to use if-then-else, you
could look into the visitor pattern, or you could conceivably create
a HashMap<Class<?>,Interf> that would map A.class, B.class,
etc., to some interface object that calls the correct doStuff. But
I haven't worked out the details. (Actually, the "visitor pattern" probably wouldn't be appropriate unless you have some sort of complex structure composed of objects of type X.)
Separate a DoStuffOperation, create the relative factory and use them.
public interface DoStuffOperation<T> {
String doStuff(T x);
}
public class ADoStuffImpl implements DoStuffOperation<A> {
public String doStuff(A x) {
return "doStuff<A>";
}
}
public class ADoStuffWithFlagImpl implements DoStuffOperation<A> {
public String doStuff(A x) {
return "doStuffWithFlag<A>";
}
}
public class DoStuffImplFactory {
public final static <T extends X> DoStuffOperation<X> getDoStuff(Class<T> xClass,boolean flag) {
DoStuffOperation<X> impl = null;
if(xClass.equals(A.class))
{
if(flag)
impl = (DoStuffOperation)new ADoStuffWithFlagImpl();
else
impl = (DoStuffOperation)new ADoStuffImpl();
}
}
return impl;
}
}
public class Y implements InterfaceY {
public String doStuff (X x, Boolean flag) {
return DoStuffImplFactory.getDoStuff(x.getClass(),flag).doStuff(x);
}
}
In this way you don't have to refactor call to Y.doStuff() or X and derived classes.
You can't remove at all some sort of instanceof to decide which implementation of doStuff() use unless X classes implements a DoStuffCreator interface like:
interface DoStuffCreator {
DoStuffOperation getDoStuffOperation(boolean flag);
}
X and A are your classes. You can also construct using reflection or other automatic way (external property file and so on).

Categories