Calling Methods from Enums - java

Is there anyway to call a method from an enum? For example:
public enum Skills {
FIRE(callMethod());
}
public void callMethod(){
//do stuff
}

You can call a static method or a method of another class as a constructor argument to an enum constant, but be aware that static fields of enums are initialized at weird times as compared with other kinds of classes.
public enum Skills {
FIRE(callMethod());
private Skills( Object oIgnored ) {
}
}
public static Object callMethod(){
//do stuff
return null;
}
or
public enum Skills {
FIRE;
private Skills() {
callMethod();
}
}
public static void callMethod(){
//do stuff
}

Related

How to use advanced methods

So, I've been working on my method building with arguments and such, but I've come across a dillema. If I were to do this:
public static void setStat() {
}
Is it possible to create "Sub-Methods" in this case? I'll give an example:
public static int attack(int attack) {
return attack;
}
public static int defense(int defense) {
return defense;
}
Then tie the "Super Method" (setStat()) to the "Sub-Methods" like so:
setStat().attack(4);
If it is possible, please provide an example on how I could do this.
Then you have to return the current instance i.e. this from your setStat() method and it should be changed from ,
public static void setStat() {
}
To
public ThisClass setStat() {
//your logic
return this;
}
public int attack(int attack) {
return attack;
}
Then you can try to do this,
object.setStat().attack(4);
You can achieve this by moving your methods from static to instance methods and deal with current this object.

Get enum size from parent interface in java

I have an interface ParentInterface and have multiple enums that implement it: ChildEnum1 and ChildEnum2. I have a method to which I pass the ParentInterface as a parameter.
Based on what ChildEnum is passed to this method, I want to get the size of the enum. How can I do this? The values.length() method works only on enums, but we are only passing in the ParentInterface to the caller.
How can we achieve this?
With reflection, using Class#getEnumConstants() (quick and dirty demo):
package com.stackoverflow.so21821751;
public class Test {
interface ParentInterface {
void someMethod();
}
static enum ChildEnum1 implements ParentInterface {
FOO, BAR, LOL;
#Override
public void someMethod() {
// something
}
}
static enum ChildEnum2 implements ParentInterface {
FOO, BAR;
#Override
public void someMethod() {
// something
}
}
public static void main(final String[] args) {
foo(ChildEnum1.BAR); // 3
foo(ChildEnum2.FOO); // 2
}
private static void foo(final ParentInterface i) {
System.out.println(i.getClass().getEnumConstants().length);
}
}

Elegant way to Extend Enums

I have a requirement that is close to extending enums and since that is not possible, after doing some research online, I came up with this approach of using interfaces and making the enums extend them.
My problem is that I have a few basic types A,B and a flag for each type that says if that has to be checked. Similarly I have some extended types C... which do the same stuff after checking their flags.
Here is the code that does this
Type Interface:
public interface Type {
public String name();
}
Here is the class that uses the basic types
public class BasicChecker {
private static boolean checkA = false;
private static boolean checkB = false;
public enum BasicType implements Type {
A, B;
}
public static boolean isCheckA() {
return checkA;
}
public static void setCheckA(boolean checkA) {
BasicChecker.checkA = checkA;
}
public static boolean isCheckB() {
return checkB;
}
public static void setCheckB(boolean checkB) {
BasicChecker.checkB = checkB;
}
public static void doStuff(String message, Type type) {
if (type.name().equalsIgnoreCase(BasicType.A.name())) {
doStuff(message, isCheckA());
} else if (type.name().equalsIgnoreCase(BasicType.B.name())) {
doStuff(message, isCheckB());
}
}
protected static void doStuff(String message, boolean flag) {
if (someCheckMethod() && flag) {
doStuff(message, flag);
}
}
private static boolean someCheckMethod() {
return false;
}
}
And this is the class that uses extended types
public class ExtendedChecker extends BasicChecker {
private static boolean checkC = false;
public enum ExtendedType implements Type {
C;
}
public static boolean isCheckC() {
return checkC;
}
public static void setCheckC(boolean checkC) {
ExtendedChecker.checkC = checkC;
}
public static void doStuff(String message, Type type) {
BasicChecker.doStuff(message, type);
if (type.name().equalsIgnoreCase(ExtendedType.C.name())) {
doStuff(message, isCheckC());
}
}
}
What I am trying to solve now is to remove all the if else cases from log method. I am also trying to see if there is a better way to do this. Please ignore the statics. I do want them to be static fields and methods.
I'm having trouble understanding exactly what you're trying to do from your description, but you may find abstract methods in enums to be useful.
For example, you could add an abstract method "foo" to your enums:
public enum BasicType implements Type {
A {
public void foo(String message) {
// Do special A stuff
}
}, B {
public void foo(String message) {
// Do special B stuff
}
};
public abstract void foo(String message);
}
And you could then use that method like this:
public static void doStuff(String message, Type type) {
type.foo(message);
}
Naturally, you could put any such abstract methods in an interface you extend, if that's useful.
public class BasicChecker {
private static final Set<Type> _doCheck = Collections.newSetFromMap(new ConcurrentHashMap<Type,Boolean>());
public enum BasicType implements Type {
A, B;
}
public static boolean isCheck(Type type) {
return return _doCheck.contains(type);
}
public static void setCheck(Type type, boolean check) {
if(check) {
_doCheck.add(type);
} else {
_doCheck.remove(type);
}
}
public static void doStuff(String message, Type type) {
doStuff(message, isCheck(type));
}
}

Is it possible to have an enum that contains constructors for objects?

I'm testing out a different sort of pattern. I've already got the code working in a switch statement, but I'd like to try something a little more ecclectic... for research purposes.
Say I have 4 classes, Class1, Class2, Class3, and Class4 that all extend BaseClass. I want to put them into an enum, like so:
enum ClassFactories {
Class1(Class1.class),
Class2(Class2.class),
Class3(Class3.class),
Class4(Class4.class);
private final Class factory;
ClassFactories(Class factory) {
this.factory = factory;
}
public BaseClass generate() {
BaseClass b = null;
try {
b = (BaseClass)this.factory.newInstance();
} catch (Exception e) {
// handle any exceptions
}
return f;
}
}
In a factory method that is passed an int, I want to be able to do something like this:
public void fakeMethod(int type) {
BaseClass someClass = ClassFactories.values()[type].generate();
someClass.doStuff();
}
Is there a cleaner/easier way of doing this? I'm not so much concerned with readability (right now), I'm just curious if this is possible.
Yes, this is possible. Something like a 'Template Method' approach. So for example
public enum ClassFactory {
Class1() {
#Override public void generate() {
System.out.println("I'm in Class 1.");
}
},
Class2() {
#Override public void generate() {
System.out.println("I'm in Class 2.");
}
};
//template method
public abstract void generate();
private static final Map<Integer, ClassFactory > lookup
= new HashMap<Integer, ClassFactory >();
static {
for (ClassFactory s : EnumSet.allOf(ClassFactory.class))
lookup.put(s.getIntValue(), s);
}
public static ClassFactory getValue(int intValue) {
return lookup.get(intValue);
}
}
INVOCATION CODE
With the use of static imports, the client code calling this enumeration would look like:
Class1.generate();
Class2.generate();
//or better...
getClass().generate();
Or
public void fakeMethod(int type) {
ClassFactory.getValue(type).generate();
}

Method as parameter with signature contract?

I would like to know how to create a contract with the caller for the Method parameter in the event the method has parameters itself. So that I use...
ClassA {
String string_ = "HI";
public static void subscribe(Object class, Method action) {
action.invoke(class, string_);
}
}
ClassB {
ClassB() {
ClassA.subscribe(this, this.getClass().getMethod("load", String.class));
}
public void load(String input) {
if(input.equals("HI")) {
...
}
}
}
I would like to know how to ensure the Method passed as "action" takes String as a parameter (i.e. ensure Method action == load(String){})? Is there something like this available:
public static void subscribe(Object class, Method action(String.class)) {
I want to do it in the method signature of subscribe so that it is obvious to the calling class (ClassB) that it needs to be prepared to take an argument of specified type.
EDIT: Updated last code bit so not to appear as if Method was generic. Poor choice of using <> on my part to represent an example of what I was trying to convey.
There's no way to do that in Java. The Method class is not generic, and there is no way for it to be so, because methods can take any number of parameters, and there is no way to make a class generic over a variable number of types.
Probably the best you can do is to declare your own type to use instead of Method:
public interface Action<T, P> {
public void invoke(T target, P parameter);
}
Then:
public static <T> void subscribe(T obj, Action<T, String> action) {
action.invoke(obj, string_);
}
ClassB() {
ClassA.subscribe(this, new Action<ClassB, String>() {
public void invoke(ClassB target, String parameter) {
target.load(parameter);
}
});
}
In C# there are means to achieve what you are trying to do but I can't think of a way to ensure that at compile time for java.
can you resort to using intefaces?
interface ILoader{
void load(String input);
}
ClassA {
String string_ = "HI";
public static void subscribe(ILoader loader) {
loader.load( string_);
}
}
ClassB implements ILoader {
ClassB() {
ClassA.subscribe(this);
}
public void load(String input) {
if(input.equals("HI")) {
...
}
}
}
Couldn't you use a slight modification of the Command Pattern?
puclic interface LoadCommand {
public load(String input);
}
public class ClassB implements LoadCommand {
public load(String input) {
// do stuff here
}
}
public class ClassA {
String myInput = "HI";
public static void subscribe(LoadCommand command) {
command.load(myInput)
}
}
The load method in the LoadCommand interface takes one String argument.

Categories

Resources