I'm looking for a way to be able to define a method for each enum instance. We all know about the code construction at the bottom of this page.
The difference I'm looking for is to be able to define one or more abstract methods for each enum in a separate file that is verified compile-time. Meaning if someone were to add another enum instance I would get a compile-time error and not a run-time error which is what I get with the construction at the bottom of this page.
The reason for the request is that in some code I'm looking at there are many methods that should be defined per enum but are really unrelated to the enum definition so I'd like to place them in separate files but not lose the benefits of the "standard" way of solving this.
public enum MyEnum {
X {
public void calc(Outer o) {
// do something
}
},
Y {
public void calc(Outer o) {
// do something
}
};
// abstract method
abstract void calc(Outer o);
}
Consider the folowing code:
interface Delegate{
void calc();
}
enum TestEnum {
EnumValue1(new Delegate() {
#Override
public void calc() {
}
}),
EnumValue2(new Delegate() {
#Override
public void calc() {
}
});
private Delegate delegate;
TestEnum(Delegate d){
this.delegate = d;
}
public Delegate getDelegate() {
return delegate;
}
}
public class Test {
public static void main() {
TestEnum.EnumValue1.getDelegate().calc();
TestEnum.EnumValue2.getDelegate().calc();
}
}
You cannot define methods for classes outside of a class!
You could define a callback interface that each enum instance had to have an instance of:
public interface MyEnumCallback {
doStuff(final Outer o)
}
Then your enum would look something like
public enum MyEnum {
X(new XCallback()),
Y(new YCallbaxk());
private final MyEnumCallback callback;
public MyEnum(final MyEnumCallback callback) {
this.callback = callback;
}
public <Whatever> call(final Outer o) {
callback.doStuff(o);
}
}
This separates your Enum from the methods as you wanted - it would also throw a compile time error if someone didn't provide an implementation of MyEnumCallback to the constructor of the Enum instance.
Related
I'm attempting to define a generic abstract class that handles the processing/retrying logic of the implementing class. I want all implementing classes to pass a "process" and "fail" function that is executed by the abstract class. The abstract class also holds retry attempt logic and some other generic boilerplate code that I would like to reuse.
Specifically, I have the following abstract class:
public abstract class EnvelopeDispatcher<T> {
protected Consumer<T> processFn;
protected Consumer<T> failFn;
private MetricsRegistry metricsRegistry;
public EnvelopeDispatcher(MetricsRegistry metricsRegistry, Consumer<T> processFn, Consumer<T> failFn) {
this.metricsRegistry = metricsRegistry;
this.processFn = processFn;
this.failFn = failFn;
}
protected void process(T envelope) {
//abstract processing logic calling processFn and failFn
}
}
And the following implementing class:
public class ActionEnvelopeDispatcher extends EnvelopeDispatcher<ActionEnvelope> implements Consumer<ActionEnvelope> {
public ActionEnvelopeDispatcher(MetricsRegistry metricsRegistry ) {
super(metricsRegistry, this::processEnvelope, this::failEnvelope)
}
#Override
public void accept(#NonNull ActionEnvelope envelopeToProcess) {
super.process(envelopeToProcess);
}
private void processEnvelope( ... ) {
//processing logic
}
private void failEnvelope( ... ) {
//failure case logic
}
}
When I attempt to call super while referencing this::processEnvelope and this::failEnvelope I get "Cannot reference this before supertype constructer has been called".
I understand why this is happening, but I'm not sure of the alternatives. Does anyone know how to get around this or a better implementation pattern?
What you could do is don't make the dispatcher abstract and create it using factory methods.
Something like this:
class EnvelopeDispatchers {
// factory method
public static EnvelopeDispatcher<ActionEnvelope> actionEnvelopeDispatcher(MetricsRegistry metricsRegistry) {
return new EnvelopeDispatcher(metricsRegistry,
EnvelopeDispatchers::processEnvelope,
EnvelopeDispatchers::failEnvelope);
}
private static void processEnvelope(ActionEnvelope env) {
//processing logic
}
private static void failEnvelope(ActionEnvelope env) {
//failure case logic
}
}
I want to be able to subclass some values in an enum, in order that I don't have to repeat code too much. Is there some way I can do this? Here's an example of what I want to achieve, which Eclipse quickly tells me is an abomination:
public enum Foo {
BAR {
#Override
public void taskA() {
System.out.println("A");
}
#Override
public void taskB() {}
},
BAZ extends BAR {
#Override
public void taskB() {
System.out.println("B");
}
};
public abstract void taskA();
public abstract void taskB();
}
BAR would have only the implementation of taskA and an empty taskB, and BAZ would have both methods - BAR's implementation of taskA, and its own implementation of taskB.
I'm not changing the values of the enum after it's declared, so why doesn't this work? I could call BAR's taskA method within BAZ, so why can't I do this?
I want to be able to subclass some values in an enum, in order that I
don't have to repeat code too much.
The usual way to share code among constant-specific methods is to declare a private static method (either in the enum itself or in a utility helper class) which contains the common code that you wish to access from your constant-specific methods.
For example ...
public enum Foo {
BAR {
#Override
public void taskA() {
commonToTaskAandB();
System.out.println("B");
}
#Override
public void taskB() {}
},
BAZ {
#Override
public void taskB() {
commonToTaskAandB();
System.out.println("B");
}
};
public abstract void taskA();
public abstract void taskB();
private static void commonToTaskAandB() {
// shared code here
:
:
}
}
Note that the code "BAZ extends Bar" is illegal because BAZ is not a type. BAZ is an instance of your Enum<Foo> type. An instance cannot extend another type. It is incorrect to apply object-oriented principles like inheritance to enum constants because, in Java, enum constants are instances of a class and not classes themselves.
Enum-Constants are objects (instances), not classes. You can only subclass classes.
However even that will not work: you can only extend enums with anynomous inner classes.
You will have to find another solution for your use case. You could:
use a static method for the shared code
call BAR.taskA() in BAZ
make taskA not abstract and put your code there
use normal constants, instead of enums
But my favorit is:
inject behaviour instead of overriding!
Example code:
class Behavior {
public static Runnable A = new Runnable() {
public void run() {
System.out.println("A");
}
}
public static Runnable B = new Runnable() {
public void run() {
System.out.println("B");
}
}
public static Runnable DO_NOTHING = new Runnable() {
public void run() {
}
}
}
public enum Foo {
BAR(Behavior.A, Behavior.DO_NOTHING),
BAZ(Behavior.A, Behavior.B);
private final Runnable mechanismA;
private final Runnable mechanismB;
private Foo(Runnable mechanismA, Runnable mechanismB) {
this.mechanismA = mechanismA;
this.mechanismB = mechanismB;
}
public void taskA() {
mechanismA.run;
}
public void taskB() {
mechanismB.run;
}
}
Pros of this solution:
The code explicitly defines the behavior of each enum constant - no implicit calculations => easier to read
You can use inheritance, etc in the Behavior-class
You can easily switch behaviorA and behaviorB - or reuse that code anywhere else
If you have Java8 available you can even shorten the code to this:
public static Runnable A = () -> {
System.out.println("A");
};
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.
I frequently find myself wanting to write generic class definitions of the form
public class Foo<ActualType extends Foo<ActualType>>
For example in a setup like this:
public interface ChangeHandler<SourceType> {
public void onChange(SourceType source);
}
public class Foo<ActualType extends Foo<ActualType>> {
private final List<ChangeHandler<ActualType>> handlers = new ArrayList<>();
public void addChangeHandler(ChangeHandler<ActualType> handler) {
handlers.add(handler);
}
#SuppressWarnings("unchecked")
protected void reportChange() {
for (ChangeHandler<ActualType> handler: handlers)
handler.onChange((ActualType) this);
}
}
public class Bar extends Foo<Bar> {
// things happen in here that call super.reportChange();
}
public static void main(String[] args) throws IOException {
Bar bar = new Bar();
bar.addChangeHandler(new ChangeHandler<Bar>() {
#Override
public void onChange(Bar source) {
// Do something with the changed object
}
});
}
The change-event here is just an example. This is more of a general problem that I'm having whenever I would like to allow a super-class to provide functionality that is "individualized" to each specific sub-class (not sure how to phrase this better... in the example above the "individualization" is the fact that the ChangeHandler is called with an object of the actual sub-type (Bar) not with the type of the super-class (Foo) that is calling the handler).
Somehow this approach seems a bit messy to me. And it actually allows for potential issues since nothing prevents me from then defining:
public class Baz extends Foo<Bar> { /* ... */ }
Is there a cleaner alternative?
The holy grail would be some type parameter that is always defined to contain the current class, like a static version of this.getClass() that would allow me to write something like this instead:
public class Foo {
private final List<ChangeHandler<this.Class>> handlers = new ArrayList<>();
public void addChangeHandler(ChangeHandler<this.Class> handler) {
handlers.add(handler);
}
protected void reportChange() {
for (ChangeHandler<this.Class> handler: handlers)
handler.onChange(this);
}
}
Where this.Class would be equal to Bar for classes of type Bar.
It is a really abstract problem. In my opinion the short answer to "how to make this cleaner" is: only use generics where it is needed.
public class List<T extends List<T>>
What is this trying to express (substituted)? A list which only allows to hold (T extends) other lists which themselves hold Ts (List) which as we know from before are Lists which only allow to hold ... and so on. Kind of circular, I don't see how you would end up with something like that?
public interface ChangeHandler<SourceType> {
public void onChange(SourceType source);
}
Why do you want to use generics here? If you want to have a change handler which can handle several resource types, then you can either create a super class from which all actual sources inherit or you create an interface which is implemented by the sources. Like that you can exactly specify what is exposed by the sources. Alternatively the source can create a source object when notifying instead of passing "this" (then it is more like a message). For example:
public interface ChangeHandler {
public void onChange(Source source);
}
public abstract class Source {
private List<ChangeHandler> handlers;
protected int nr;
public Source(int nr) {
this.nr = nr;
}
public abstract Something getSomething();
public String toString() {
return "SRC" + nr;
}
...
private notify(int index) {
handlers.get(i).onChange(this);
}
}
public class Foo extends Source {
public Foo(int nr) {
super(nr);
}
public String toString() {
return super.toString() + "Foo";
}
public Something getSomething() {
return new Something();
}
}
You never need to cast... or do you? I'm not sure if I understand the problem.
I would recommend that we simply use <This> to represent the "self type". No need for bound, since it looks complicated, doesn't deliver the intention, and cannot enforce the constraint anyway.
public class Foo<This> {
private final List<ChangeHandler<This>> handlers = new ArrayList<>();
public void addChangeHandler(ChangeHandler<This> handler) {
handlers.add(handler);
}
#SuppressWarnings("unchecked")
protected void reportChange() {
for (ChangeHandler<This> handler: handlers)
handler.onChange( (This)this );
}
}
Notice the cast (This)this.
See also Java generics: Use this type as return type?
I never use type parameters to pass "ActualType" because then it is impossible to extend the object:
public class Bar extends Foo<Bar> {
// things happen in here that call super.reportChange();
}
public class Bar2 extends Bar{
// ...
}
Bar2 "ActualType" is still Bar, and there is nothing you can do: you won't be able to use ChangeHandlers for Bar2
To avoid the issue, the only possible fix I see is to delegate the cast operation to an other class (you could also use a default method in the ChangeHandler interface).
Here is a possibility:
public class Foo // no more type parameter
{
private final List<FooCaster<?>> casterHandlers = new ArrayList<>();
/**
* unsafe because you could register a ChangerHandler of any type.
* worst of all, everything is unchecked cast so the error could show up late.
*/
public <T> void addChangeHandler(ChangeHandler<T> handler) {
casterHandlers.add(new FooCaster<T>(handler));
}
protected void reportChange() {
for (FooCaster<?> caster: casterHandlers) {
caster.reportChange(this);
}
}
class FooCaster<T> {
protected ChangeHandler<T> ch;
protected FooCaster(ChangeHandler<T> ch) {
this.ch = ch;
}
#SuppressWarnings("unchecked")
public void reportChange(Foo f) {
ch.onChange((T)f);
}
}
}
Personnaly in the case of broadcasting changes to listener/changehandlers, I'm enclined to externalize the process to an other class, which makes it possible to use parameter types properly and avoid unsafe casts.If you are still willing to use reportChange() from within the foo object, here is a possible implementation (otherwise you could store a T reference in the Broadcaster).
public class Broadcaster<T extends Foo> {
protected final List<ChangeHandler<? super T>> changeHandlers;
public Broadcaster() {
this.changeHandlers = new ArrayList<>();
}
public void startListeningTo(T obj) {// only T type objects are accepted
obj.registerBroadcaster(this);
}
public void addChangeHandler(ChangeHandler<? super T> changeHandler) {
changeHandlers.add(changeHandler);
}
void reportChange(Foo obj) {
T o = (T)obj;
for(ChangeHandler<? super T> c : changeHandlers) {
c.onChange(o);
}
}
}
public class Foo {
private final List<Broadcaster<?>> broadcasters = new ArrayList<>();
// cannot be accessed from outside of the package, only Broadcaster.startListeningTo(T o) can be used
final void registerBroadcaster(Broadcaster<?> b) {
broadcasters.add(b);
}
public final void reportChange() {
for (Broadcaster<?> b: broadcasters) {
b.reportChange(this);
}
}
}
public class Bar extends Foo {
// things happen in here that call super.reportChange();
}
public static void test() {
Broadcaster<Bar> broadcaster = new Broadcaster<>();
broadcaster.addChangeHandler(new ChangeHandler<Bar>() {
#Override
public void onChange(Bar obj) {
// do something
}
});
//note that you can use the same broadcaster for multiple objects.
Bar b = new Bar();
broadcaster.startListeningTo(b);
b.reportChange();
}
Note that you will not be able to add changeHandlers from within Bar (but is it really the object's job to register changeHandlers for itself?).
Consider the simple example below of implementing a method in an Enum. One problem with this method is that, when you have a lot of enum instances, you visually can no longer see them all at once, as a list. That is, if we had many toys, I would like to see "DOLL, SOLDIER, TEDDYBEAR, TRAIN, ETC", together, in one long list, and then after that list I could implement any needed methods, e.g. methods that are abstract in the enum itself.
Is there any way to do this? Or do you have to implement the methods when you declare the individual enum instances, as in the example below?
public enum Toy {
DOLL() {
#Override public void execute() {
System.out.println("I'm a doll.");
}
},
SOLDIER() {
#Override public void execute() {
System.out.println("I'm a soldier.");
}
};
//abstract method
public abstract void execute();
}
One way that comes to mind is to leave the implementation of the abstract methods to separate implementation classes, something like:
interface ToyBehaviour {
void execute();
}
public enum Toy {
DOLL(new DollBehaviour()),
SOLDIER(new SoldierBehaviour());
private final ToyBehaviour behaviour;
Toy(ToyBehaviour impl) {
behaviour = impl;
}
public void execute() {
behaviour.execute();
}
}
class DollBehaviour implements ToyBehaviour {
public void execute() {
System.out.println("I'm a doll.");
}
}
This setup would allow you to create behaviour classes in separate files in the case that your implementation has enough complexity to warrant separation.
In the case that the implementation is simple enough to include it into the one enum class, you can put the interface and behaviour classes as children of the enum class:
public enum Toy {
// enum values
DOLL(new DollBehaviour()),
SOLDIER(new SoldierBehaviour());
private final ToyBehaviour behaviour;
Toy(ToyBehaviour impl) {
behaviour = impl;
}
public void execute() {
behaviour.execute();
}
// behaviour interface
interface ToyBehaviour {
void execute();
}
// behaviour implementation (sub)classes
static class DollBehaviour implements ToyBehaviour {
public void execute() {
System.out.println("I'm a doll.");
}
}
// etc ...
}
I would probably opt for the first implementation myself, unless the hierarchy of implementation classes is very trivial.
If you want more compact enum declarations, the only ways I can think of to do it are :
if you can construct your methods out of initializer variables:
public enum Toy {
DOLL("doll"),SOLDIER("soldier");
private Toy(String name){ this.name=name;}
public void execute(){ System.out.println("I'm a "+name );}
}
or, slightly more complicated, kind of the same with functions, if the behavior is more complex -
abstract class SomeToyMethod {
abstract void execute();
public SomeToyMethod DOLL_METHOD = new SomeToyMethod(){
public void execute(){ System.out.println("I'm a doll");})
public SomeToyMethod SOLDIER_METHOD = new SomeToyMethod(){
public void execute(){ System.out.println("I'm a soldier");})
public enum Toy {
DOLL(SomeToyMethod,DOLL_METHOD),SOLDIER(SomeToyMethod.SOLDIER_METHOD);
private Toy(SomeToyMethod method){ this.method=method;}
public void execute(){ method.execute();}
}
You could try something like:
public enum Toy {
DOLL,
SOLDIER,
ANOTHER_TOY;
public static void execute(Toy toy) {
switch(toy) {
case DOLL:
System.out.println("I'm a doll.");
break;
case SOLDIER:
System.out.println("I'm a soldier.");
break;
case ANOTHER_TOY:
System.out.println("I'm another toy.");
break;
}
}
}
Not very pretty but it keeps your enum declarations together.