Putting a Method in an array - java

So I want to make an array that has methods in it. For example:
public static void givePointBoost(){
points += 30};
or
public static void giveSword(){
Actions.giveItems(Items.diamond_sword);
Actions.givePotion(Potions.slowness);};
As you can see, both of these methods are voids. What I want to do is have an array that has all these voids in it so that I can pick a random method out of it later on. But I can't put it into an array because It says that I can't have an array of voids. When I try to make it an array of objects, It says that it can't switch from object to void. So my question is:
How do you get methods inside of Arrays?

In Java, you do not have delegates or function pointers, which you can store in collections or arrays like objects, so you have to employ the Command Pattern to achieve this. Basically, you wrap a method in an object that you pass on. The receiver can then access the method via the object.
Create a command interface:
interface ICommand {
public void execute();
}
Wrap a method (or multiple) in a class via inheritance...
class SpecificCommand implements ICommand {
public void execute() {
// Do something...
}
}
...or wrap existing methods directly in an anonymous class:
class SomeClass {
private void someMethod(int someValue) {
// Some stuff...
}
public static void main(String[] args) {
List<ICommand> commands = new ArrayList<>();
// Do something...
// Add command directly
ICommand command = new ICommand() {
#Override
public void execute() {
someMethod(42);
}
}
// Do something....
}
}
Call the commands from the list in a loop (or single):
for (ICommand command : commands) {
command.execute();
}

Let's sort things out.
Arrays in Java can only contain objects or primitives.
Collections in Java can only contain objects.
What you're looking for is called a Command Pattern.
https://www.tutorialspoint.com/design_pattern/command_pattern.htm
You'll have a list of objects, each of them with single method, let's say "execute". With polymorphism, each of this objects will do something different.
Here's an example:
import java.util.ArrayList;
import java.util.List;
public class CommandPatternExample {
public static void main(String[] args) {
List<Command> commands = new ArrayList<>();
commands.add(new GiveBoostCmmand("knight"));
commands.add(new GiveItemCommand("sword", "knight"));
for (int i = 0; i < 3; i++) {
commands.get((int)(Math.random() * commands.size())).execute();
}
}
public interface Command {
void execute();
}
static class GiveBoostCmmand implements Command {
private String targetName;
public GiveBoostCmmand(String targetName) {
this.targetName = targetName;
}
public void execute() {
System.out.println("Boosting " + this.targetName);
}
}
static class GiveItemCommand implements Command {
private String itemName;
private String targetName;
public GiveItemCommand(String itemName, String targetName) {
this.itemName = itemName;
this.targetName= targetName;
}
public void execute() {
System.out.println("Giving " + this.itemName + " to " + this.targetName);
}
}
}

Are you trying to say you want the result of the method to be added to the array?
As far as i know, i don't think you can put a method inside an array.
What you could do is create an interface, and provide implementations and then add those objects to an array. That way you could pick a random object and call the method defined in the interface.

The main question is Why do you need methods in an array?
The other solutions using the Command pattern are a great solution. But seeing your code I believe that you also should put that pattern in a specialized class whose purpose will be to initialize the pool of possible actions and select one at random when you need to.
Which would translate to the following UML
|RandomActionCaller |
|------------------------|
|- List<Command> commands|
|------------------------|
|+ selectRandomEffect() |
In the constructor you prepare the basic list of possible outcome, please refer to the other answers about the Command pattern. Maybe also add a method to add more commands to the list of commands from the outside of the class, this can be usefull.
The select random effect method would only select a random number between 0 and commands.size()-1, get the command instance and execute it. If you need to execute it somewhere else in your code just return it from the select random effect method.

Related

Java - List, array type thing of different type objects?

So I have a bunch of java classes that are structured like this
class Something {
public static String name;
public static String description;
public void run(String[] args);
}
The problem is, they are all different types. So if I try to make a HashSet of them and iterate over them
HashSet<Object> things = new HashSet<Object>();
things.add(new Something());
things.add(new Otherthing());
things.forEach(thing -> {
thing.run();
})
it gives this error
symbol: variable run
location: variable thing of type java.lang.Object
So how can I make an iterable Set of these objects and use their properties?
They need to be of the same type to be used like that. Luckily, we can fix this by implementing a fitting functional interface.
public class Something implements Runnable {
public String name;
public String description;
#Override
public void run() {
System.out.println("something");
}
}
Runnable has the method run() that takes no arguments and returns nothing (aka it has to do something).
So this works only if you're not actually going to be using the String array as an argument, as you don't include it in your calling of run(). However, if you do need it, you must change the implemented interface to Consumer instead of Runnable, with accept() instead, as this method actually takes an argument as opposed to run().
public class Main {
public static void main(String[] args) {
HashSet<Runnable> things = new HashSet<>();
things.add(new Something());
things.add(new Something2());
things.forEach(thing -> {
thing.run();
});
}
}
Now, we set the HashSet to the type of the implemented interface, and it works!
Here's the other class:
public class Something2 implements Runnable {
public String name;
public String description;
#Override
public void run() {
System.out.println("something2");
}
}
Now you can create as many classes as you want and have their methods do different things, while still being able to gather them in the same set(as long as they implement the same type)!
Side note: if you didn't need the attributes, you could've used lambda expressions to implement different versions of run() (or accept(), or any other functional interface-method).

Design Approach and Using Reflection to run methods in Java

I have a question. I have multiple classes in a package: Let's say package is
com.myPackage.first
And this package has the following classes:
firstGood
secondGood
thirdBad
fourthGood
Each of these classes have a method with the same name but different implementation. So say each have a one particular function called:
public void runMe(){
}
For now I want to come up with a way to given a class name, it'll go inside the class and run that particular method.
So conceptually, my method will look like those:
ArrayList<Class> classList ; // where classList is a list of classes I want to run
public void execute(){
for(Class c : classList){
// Go inside that class, (maybe create an intance of that class) and run the method called run me
}
}
or
public void execute(Class c, String methodToRun){
for(Class c : classList){
// Go inside that class, (maybe create an intance of that class) and run the method called run me
}
}
For now. what I have been able to do is get the name of the classes I want to run the
runMe()
method. So I have been able to come with a way to get the arraylist of classes I want to run. So what I need help with is coming up with a method such that it takes a class name and run the method I want it to. Any help is appreciated. Thanks
I suggest having a look at Class.forName ( ... ) to get the class object, Class.newInstance(); if your classes have a default constructor (or Class.getDeclaredConstructor(...) otherwise) to create a new instance and then Class.getDeclaredMethod( ... ) to find the method and invoke it.
All of this without any regard if your idea is really a good one, since I really didn't quite understand WHY you want to do what you want to do...
interface Me {
void runMe();
}
Then let all classes implement Me.
And have a list of Mes
List<Class<Me>> ...
Then
void test(Class<Me> cl) {
Me me = cl.newInstance();
me.runMe();
}
My adage is always use reflection to solve a problem - now you have two problems. In view of that have you considered a simple pattern like this:
interface Runner {
public void runMe();
}
static abstract class BaseRunner implements Runner {
public BaseRunner() {
// Automagically register all runners in the RunThem class.
RunThem.runners.add(this);
}
}
class FirstGood extends BaseRunner implements Runner {
#Override
public void runMe() {
System.out.println(this.getClass().getSimpleName() + ":runMe");
}
}
class SecondGood extends BaseRunner implements Runner {
#Override
public void runMe() {
System.out.println(this.getClass().getSimpleName() + ":runMe");
}
}
static class RunThem {
static final Set<Runner> runners = new HashSet<>();
static void runThem() {
for (Runner r : runners) {
r.runMe();
}
}
}
public void test() {
Runner f = new FirstGood();
Runner s = new SecondGood();
RunThem.runThem();
}
Here all of your runMe objects extend a base class whose constructor installs the object in a Set held by the class that calls their runMe methods.
inline
void execute() throws Exception{
for (Class<?> c : classesList)
{
//If you don't already have an instance then you need one
//note if the method is static no need for any existing instance.
Object obj = Class.forName(c.getName());
// name of the method and list of arguments to pass
Method m = c.getDeclaredMethod(methodName,null);
//method accessibility check
if(!m.isAccessible())
m.setAccessible(true);
//invoke method if method with arguements then pass them as new Object[]{arg0...} instead of null
//if method is static then m.innvoke(null,null)
m.invoke(obj, null);
}
}
I would recommend using an Interface that defines the runMe() method and then have all your classes implement that interface. Then you would have a list of this Interface:
List<MyInterface> classes = new ArrayList<MyInterface>();
Then you could easily iterate over it and invoke "runMe()" on all of them or if you only want to invoke it for instances of a certain class you could do it like this:
public void execute(Class classForWhichToExecute) {
for (MyInterface myInterface : classes) {
if (classForWhichToExecute.isAssignableForm(myInterface)) {
myInterface.runMe();
}
}
}
Of course this wouldn't work if your method is a static method - so adding more information from your side would help.
I would suggest to use an interface with a common method to override in each class. So that any class can be casted to interface and use its method to execute the method.
interface GoodAndBad{
public void runMe();
}
Implemented class
class FirstGood implements GoodAndBad{
#override
public void runMe(){
// Code to be executed
}
}
You can use execute() method as follows
public void execute(List<GoodAndBad> classList){
for(GoodAndBad c : classList){
c.runMe();
// Go inside that class, (maybe create an intance of that class) and
// run the method called run me
}
}
Change the Class to GoodAndBad interface to change the other method too.
This is loosely coupling objects to support favor over composition in Java Object Oriented Design Patterns.
Never use Strings of method names to execute a method at anytime. There are plenty of other cool solutions for that using design patterns.

How refactor the method?

There is a given method. How can we refactor it?
public void foo(Factor o){
if(o.matches(constant1)){
method1();
}else if(o.matches(constant2)){
method2();
}
}else if(o.matches(constant3)){
method3();
}
....
}
This is something called a code smell. You would want to use what's called the "command pattern" which is a design pattern to refactor this code. On mobile now, will update with an example when I get to my desk today.
Edit: Here we go.
So the command pattern is a design pattern used for this exact scenario. What you need to first do is create a command Interface.
public interface MyCommand {
public void execute();
}
Great. Next you create Command objects that hold all of your method data.
public class Method1Command implements MyCommand {
public MyVariable var;
public Method1Command(<your arguments to create method>)
{
// instantiate your command
}
public void execute()
{
// what your current method1() is;
}
}
And then you just create some kind of private class in your Main to create a HashMap of all of the commands, keyed with the value of "ConstantX."
private static Map<String, MyCommand> getMyCommands()
{
Map<String, MyCommand> commandList = new HashMap<String, MyCommand>();
MyCommand c;
c = new Method1Command();
commandList.put("constant1", c);
c = new Method2Command();
commandList.put("constant2", c);
c = new Method3Command();
commandList.put("constant3", c);
return commandList();
}
Then, in the refactored method you would simply do the following:
public void foo(Factor o)
{
cl.get(o).execute();
}
This, however, assumes that o has some kind of toString method inside it, or if you have some method inside of o that you use to get the command it would be something like this: cl.get(o.getMyCommand()).execute();
You can make an array containing the constants, and a Map containing constant-string pairs (String is the name of the method), use reflection and do something like:
public void foo(Factor o) {
for(int i = 0; i < constans.length; i++) {
if(o.matches(constant)) {
Method method =
YourClass.class.getMethod(myMap.get(constant), null);
method.invoke(null);
}
}
}

Writing a Java class with instance parameters, retrieve parameters and print results

Basically, I need to create a new simple Java class which retrieves values from my forms (that I have designed as my process and is deployed as a web application), once the method in the Java class is invoked then the Java class should just simply print out the values (e.g. system.println.out...) it got from the form in a console or text file.
Create a class with some instance parameters. Print a line stating the initial values of these parameter(s).
I am new to Java and have just started few days ago but have this requirement as part of a project.
Please someone help to write this Java class.
I recommend you to read some java beginners books (or the javadoc) in order to understand the Class constructor concept in java before trying to do write something wrong.
A rough class may be like this :
public class myClass{
int param1;
int param2;
public myClass(int firstparam, int secondparam){
this.param1 = firstparam;
this.param2 = secondparam;
}
}
public static void main(){
myClass c = new myClass(1,2);
System.out.println(c.param1 + c.param2);
}
If you don't understand this, please learn the java basis..
You can simply create a class and its constructer like:
public class Test {
//a string representation that we will initialize soon
private String text;
//Firstly you have to instantiate your Test object and initialize your "text"
public Test(String text) {
this.text = text;
//System.out.println(text);
//You can print out this text directly using this constructor which also
//has System.out.println()
}
//You can just use this simple method to print out your text instead of using the
//constructor with "System.out.println"
public void printText() {
System.out.println(this.text);//"this" points what our Test class has
}
}
While using this class is like:
public class TestApp {
public static void main(String[] args) {
Test testObject = new Test("My Text");
/*if you used the constructor with System.out.println, it directly prints out
"My Text"*/
/*if your constructor doesn't have System.out.println, you can use our
printText() method //like:*/
testObject.printText();
}
}

Modulation of adding new Strings -> Method calls

If I have a program that does the following:
if(input=='abc'){do x}
if(input=='def'){do y}
In the future, I may want to add another piece of code like so:
if(input=='ghy'){do x}
As you can see, I am adding a new 'if' statement for a different conditional BUT using the SAME function X.
The code in future has potential to have lots of different IF statements (or switches) all of which are comparing a string vs a string and then performing a function. Considering the future expansion, I was wondering if there is a possible 'neater', 'modular' way of achieving the same results.
It's a shame I can't combine the String with a Method call in a hashtable (String, method) in Java. That way I could just store any new procedures inside a hashtable and grab the relevant method for that String.
Any ideas?
Thank you
EDIT: Thank you for everyone's solutions. I was surprised by the quantity and quality of replies I received in such a small amount of time.
Maybe you can use enum. Example:
public enum InputType
{
abc, def
{
#Override
public void x()
{
System.out.println("Another method");
}
},
ghy;
public void x()
{
System.out.println("One method");
}
}
And further:
InputType.valueOf("abc").x();
Cheers!
I guess you could always use a Map<String, Runnable> and map to anonymous Runnable implementations:
myMap.put("abc", new Runnable() { public void run() { do x } });
...
myMap.get(input).run();
You should take a look at the command pattern. There are several ways of implementing it, and frameworks such as Spring can help you do with in a clean way.
But in a simple manner here's what you could do:
1-Create a Command interface with a method that your program will have to call to do the task, say doTask()
2-Create classes for command X and Y, implementing the Command interface.
3-Create a Map<String, Command> that will map your commands (X and Y) to logical names
4-Create a configuration file of your choice, say a .properties file that will map your input to your command names: abc=X, def=Y, ghi=X
5-Your program then does lookups on the config file to know which command to run according to the input.
A lot of ifs always tell us that we could do this better. In your case better option is to use design pattern e.g. Chain of responsibility. You will have good implementation which you can dynamic change and your code will be easier to maintenance than ifs implementation.
Take a look at this adaptation chain of responsibility to your case:
Main:
public static void main(String[] args) {
ClassA classA = new ClassA(Arrays.asList("abc", "ghi"));
ClassB classB = new ClassB(Arrays.asList("def"));
classA.setNextInChain(classB); // you can always write Builder to do this
String input = "def";
classA.execute(input);
}
BaseClass:
public abstract class BaseClass {
private Collection<String> patterns = Collections.EMPTY_LIST;
protected BaseClass nextInChain;
protected abstract void doMethod(); // your doA, doB methods
public void execute(String input) {
// this replace many ifs in your previous implementation
if (patterns.contains(input)) {
doMethod();
} else {
nextInChain.execute(input);
}
}
public void setPatterns(Collection<String> patterns) {
this.patterns = patterns;
}
public void setNextInChain(BaseClass nextInChain) {
this.nextInChain = nextInChain;
}
}
Class in chain:
public class ClassA extends BaseClass {
ClassA(Collection<String> patterns) {
setPatterns(patterns);
}
#Override
protected void doMethod() {
// do A
}
}
public class ClassB extends BaseClass {...}

Categories

Resources