Java overload: how to call more specific one - java

My program parses WebAssembly instructions and makes decisions based on the context of the current instruction. So, the MWE for my algorithm looks like this:
public class Main {
public interface Context {
String name();
}
static class M implements Context {
public String name() {
return "Context M: ";
}
}
static class N implements Context {
public String name() {
return "Context N: ";
}
}
public interface Instruction {
int getId();
String run();
}
static class A implements Instruction {
public int getId() {
return 0;
}
public String run() {
return "The work of A";
}
}
static class B implements Instruction {
public int getId() {
return 1;
}
public String run() {
return "The work of B";
}
}
static void work(Context context, Instruction instruction) {
switch (instruction.getId()) {
case 0:
workOnId0(context, (A) instruction);
break;
case 1:
workOnId1(context, (B) instruction);
break;
default:
throw new RuntimeException("Failed to recognize instruction");
}
}
static void workOnId0(Context context, A instruction) {
System.out.println(context.name() + instruction.run());
}
static void workOnId1(Context context, B instruction) {
System.out.println(context.name() + instruction.run());
}
static void workOnId1(N context, B instruction) {
System.out.println("This is corner case logic for this context!");
}
public static void main(String[] args) {
N context = new N();
B instruction = new B();
work(context, instruction);
}
}
As you can see from above, when my instruction is B, then the ordinary work should happen in workOnId1, but in case my context is specifically N, I would like some special work done, which is represented by a different overload of workOnId1.
Unfortunately, the special overload never gets called. How can I make the overload resolution work?

workOnId1(Context context, B instruction) will always be called, because you have a Context object.
You are going to need to differentiate method calls by casting to N. If this doesn't work well within your model, since I'm guessing this is only a small example, you may need to rethink your overall design. A simple solution would be:
if(context instanceof N) {
workOnId1((N)context, (B)instruction);
} else {
workOnId1(context, (B) instruction);
}

you can change one line under case:1 as below to achieve your target
switch (instruction.getId()) {
case 0:
workOnId0(context, (A) instruction);
break;
case 1:
workOnId1((context instanceof N)? (N)context :context, (B) instruction); break;
default:
throw new RuntimeException("Failed to recognize instruction");
}

Related

Choosing between extended classes inside constructor

I am writing a java (processing) library for unexperienced students, and am looking for the best architecture for implementing it.
Initialization of an object should be as close as possible to this:
myObject = new General("type1");
Such that myObject will become an instance of Type1 which extends General:
class General {
public General() {}
}
class Type1 extends General {
public Type1() {}
}
class Type2 extends General {
public Type1() {}
}
As far as I know, this isn't possible (choosing between extended classes during initialization), but I'm looking for the closest solution possible.
So far, my best solution is to make a static initializer inside General:
class General {
...
static General init (String type) {
General temp;
if (type.equals("type1") {
temp = new Type1();
}
...
return temp;
}
and the initialization is:
General myObject;
myObject = General.init("type1");
This is far from ideal...
thanks.
you can make a factory class that manages initialization.
instead of doing it inside the parent.
// Empty vocabulary of actual object
public interface IPerson
{
string GetName();
}
public class Villager : IPerson
{
public string GetName()
{
return "Village Person";
}
}
public class CityPerson : IPerson
{
public string GetName()
{
return "City Person";
}
}
public enum PersonType
{
Rural,
Urban
}
/// <summary>
/// Implementation of Factory - Used to create objects.
/// </summary>
public class Factory
{
public IPerson GetPerson(PersonType type)
{
switch (type)
{
case PersonType.Rural:
return new Villager();
case PersonType.Urban:
return new CityPerson();
default:
throw new NotSupportedException();
}
}
}
The State design pattern can be a solution here. Rather than the constructor argument changing the type of the object (which isn't possible) it can set a field of the object, to make it behave as if its type is different.
package stackoverflow.questions;
public class Main {
private interface MyInterface {
String foo();
int bar();
}
private static class Type1 implements MyInterface {
#Override public String foo() { return "lorem ipsum "; }
#Override public int bar() { return 6; }
}
private static class Type2 implements MyInterface {
#Override public String foo() { return "dolor sit amet"; }
#Override public int bar() { return 7; }
}
public static class General {
private final MyInterface type;
public General(String type) {
try {
this.type = (MyInterface) Class
.forName("stackoverflow.questions.Main$" + type)
.getDeclaredConstructor().newInstance();
} catch (Exception e) {
throw new IllegalArgumentException("Invalid type: " + type);
}
}
public String method1() { return type.foo(); }
public int method2() { return type.bar(); }
}
public static void main(String... args) {
General one = new General("Type1");
General two = new General("Type2");
System.out.println(one.method1() + two.method1());
System.out.println(one.method2() * two.method2());
}
}

How do I throw an exception in my Java code?

I got a method that prints out the animals' names.
I now need an error to be printed out if the id is not one of the given ones.
How does it work?
class Methode {
static final int DEER = 0;
static final int BIRD = 1;
static final int COW = 2;
static final int PIG = 3;
public static void main(String[] args) {
printAnimal();
}
public static void printAnimal (int id) {
if (id == DEER) {
System.out.println("Deer");
}
else if (id == BIRD) {
System.out.println("Bird");
}
else if (id == COW) {
System.out.println("COW");
}
else if (id == PIG) {
System.out.println("Pig");
}
}
}
If by error you mean an Exception (otherwise I don't know why you didn't simply printed an "error" message like you did in your else if branches), then you need to create a custom class which extends Exception and throw it in a new else branch. Here is an example:
Exception:
public class NoSuchAnimalException extends Exception {
public NoSuchAnimalException(String message) {
super(message);
}
}
Test:
public static void printAnimal(int id) throws NoSuchAnimalException {
if (id == DEER) {
System.out.println("Deer");
} else if (id == BIRD) {
System.out.println("Bird");
} else if (id == COW) {
System.out.println("COW");
} else if (id == PIG) {
System.out.println("Pig");
} else {
throw new NoSuchAnimalException("No such animal");
}
}
public static void main(String[] args) {
try {
printAnimal(6);
} catch (NoSuchAnimalException e) {
System.out.println(e.getMessage());
}
}
The exception will be thrown in the last else (the id provided in method call doesn't meet the previous requirements) and will be handled in the public static void main() method.
Firstly you call your printAnimal() method without a parameter. That's no good.
Secondly, there are two kinda of exceptions in Java, checked and unchecked. You need to consider which kind you're working with.
Checked means your function must be declared by:
methodName() throws SomeException{
...}
And accordingly a caller MUST catch exceptions.
Unchecked means you can throw the exception without doing this, but other programmers aren't made aware of (and conversely, not forced to handle) any exceptions thrown.
Exceptions should be created, like classes, inheriting the base type of exception appropriate.
Checked exception
class someException extends exception{...}
Unchecked exception
class someException extends RuntimeException{...}
For non custom exceptions they are thrown like so:
The checked exception
throw new Exception ('message');
The unchecked exception
throw new RuntimeException ('message');
Please read the Java doc on exceptions.
Exceptions are an important part of OOP
(This was written on a phone, so there might be a few typos etc.)
Should use enums and switch for this task:
public class Methode {
public enum Animal {
DEER (0),
BIRD (1),
COW (2),
PIG (3);
private final int value;
private static Map valueMap = new HashMap<>();
Animal(int value)
{
this.value = value;
}
static {
for (Animal enumVal : Animal.values()) {
valueMap.put(enumVal.value, enumVal);
}
}
public static Animal valueOf(int animalId) {
return (Animal) valueMap.get(animalId);
}
public int getValue()
{
return value;
}
}
public static void main(String[] args) throws Exception {
printAnimal(1);
}
public static void printAnimal (int id) throws Exception {
Animal animal = Animal.valueOf(id);
if(animal == null) {
throw new Exception("Animal not found"); //better use own exception
} else {
switch (animal) {
case DEER:
System.out.println("Deer");
break;
case BIRD:
System.out.println("Bird");
break;
case COW:
System.out.println("COW");
break;
case PIG:
System.out.println("Pig");
break;
default:
System.out.println(animal.name());
}
}
}
}

Safe use of Enum valueOf for String comparison on a switch

How to safe implement the use of valueOf in case i get a String different than the supported on the enum ACTION. I mean is possible to force to ACTION.valueOf(valueToCompare) to get a valid value even when happens that valueToCompare is not a valid enum member
I get an expected execution when valueToCompare is "CRY" or "CRYALOT" or "cryalot" etc.
And i get java.lang.IllegalArgumentException on cases like in the code.
public enum ACTION{
CRY,
CRYALOT;
}
public static void main(String[] args) {
String valueTocompare = "posible not expected value".toUpperCase();
switch (ACTION.valueOf(valueToCompare)) {
case CRY:
System.out.println("Cry");
break;
case CRYALOT:
System.out.println("Cry a lot");
break;
default:
System.out.println("catch posible not expected value");
break;
}
}
EDIT & used SOLUTION:
I solved this by using a try-catch as #Peter Lawrey suggested:
public enum ACTION{
CRY,
CRYALOT,
NOTVALID;
}
public static void main(String[] args) {
String valueToCompare = "NOTVALID";
ACTION action;
try {
valueToCompare= "variable posible not expected value".toUpperCase();
action = ACTION.valueOf(valueToCompare);
} catch(IllegalArgumentException e){
System.out.println("Handled glitch on the Matrix");
action = ACTION.NOTVALID;
}
switch (action) {
case CRY:
System.out.println("Cry");
break;
case CRYALOT:
System.out.println("Cry a lot");
break;
default:
System.out.println("catch posible not expected value");
break;
}
System.out.println("We continue normal execution on main thread...");
}
You need to catch the IllegalArgumentException
try {
switch (ACTION.valueOf(valueToCompare)) {
}
} catch (IllegalArgumentException iae) {
// unknown
}
Or you can create your own function which does this.
public static <E extends Enum<E>> E valueOf(E defaultValue, String s) {
try {
return Enum.valueOf(defaultValue.getDeclaringClass(), s);
} catch (Exception e) {
return defaultValue;
}
}
Note: switch(null) throws a NullPointerException rather than branching to default:
Using exceptions for flow control is considered as a bad practice.
String valueToCompare = value.toUpperCase();
ACTION action = Arrays.stream(ACTION.values())
.filter(a -> a.name().equals(valueToCompare)).findFirst().orElse(ACTION.NOTVALID);
the problem here is this line:
ACTION.valueOf(valueToCompare) - you are trying to run valueOf on valueToCompare, and its erroring out since the value isn't an enum in ACTION. It's not even making the switch statement to print out the default msg.
Have a look at the changes I've done, you'll notice a few things, the main one being actionToCompare...
enum Action {
CRY,
CRYALOT,
EXAMPLE
}
public static void main(String[] args) {
Action actionToCompare = Action.EXAMPLE;
switch (actionToCompare) {
case CRY:
System.out.println("Cry");
break;
case CRYALOT:
System.out.println("Cry a lot");
break;
default:
System.out.println("catch posible not expected value");
break;
}
}
if you insist on using a String over converting it to the enum Action, wrap it in a try...catch statement so if an invalid string is passed in it can handle the error.
You can always build yourself a reverse-lookup.
enum Action {
CRY,
CRYALOT,
EXAMPLE;
// Lookup map for actions in string form.
static Map<String,Action> lookup = Arrays.stream(values()).collect(Collectors.toMap(
// Key is name in lowercase.
a -> a.name().toLowerCase(),
// Value is the Action.
a -> a));
public static Action lookup(String name) {
return lookup.get(name.toLowerCase());
}
}
public void test() throws Exception {
System.out.println(Action.lookup("cry"));
System.out.println(Action.lookup("CryAlot"));
}
A solution that does not involve exceptions in the control flow and enables mapping the enum name or the action name to the action with a default behavior in case there is no mapping entry:
public enum CryActions {
CRY_A_LITTLE("Cry a little", CryALittleActionHandler::new), CRY_A_LOT("Cry a lot", CryALotActionHandler::new), DEFAULT("Default", DefaultCryActionHandler::new);
private String actionName;
private Supplier<CryActionHandler> supplier;
private CryActions(String actionName, Supplier<CryActionHandler> supplier) {
this.actionName = actionName;
this.supplier = supplier;
PossibleCryActions.byEnumName.put(name(), this);
PossibleCryActions.byActionName.put(actionName, this);
}
public void handleAction() {
supplier.get().handleAction();
}
public String getActionName() {
return actionName;
}
public static CryActions fromEnumName(String enumName) {
return PossibleCryActions.byEnumName.computeIfAbsent(enumName, x -> DEFAULT);
}
public static CryActions fromActionName(String actionName) {
return PossibleCryActions.byActionName.computeIfAbsent(actionName, x -> DEFAULT);
}
private static class PossibleCryActions {
private static Map<String, CryActions> byEnumName = new HashMap<>();
private static Map<String, CryActions> byActionName = new HashMap<>();
}
}
public interface CryActionHandler {
void handleAction();
}
public class CryALittleActionHandler implements CryActionHandler {
#Override
public void handleAction() {
System.out.println("Just crying a little...");
}
}
public class CryALotActionHandler implements CryActionHandler {
#Override
public void handleAction() {
System.out.println("Crying a river...");
}
}
public class DefaultCryActionHandler implements CryActionHandler {
#Override
public void handleAction() {
System.out.println("Just crying as default behavior...");
}
}
public class Main {
public static void main(String[] args) {
CryActions.fromEnumName("CRY_A_LITTLE").handleAction();
CryActions.fromEnumName("CRY_A_LOT").handleAction();
CryActions.fromEnumName("CRY_UNEXPECTEDLY").handleAction();
CryActions.fromActionName("Cry a little").handleAction();
CryActions.fromActionName("Cry a lot").handleAction();
CryActions.fromActionName("Cry unexpectedly").handleAction();
}
}
Kotlin version:
inline fun <reified T : Enum<T>> safeValueOf(name: String, defaultValue: T): T =
try {
java.lang.Enum.valueOf(T::class.java, name) ?: defaultValue
} catch(e: IllegalArgumentException) {
defaultValue
}

How to store name of class in a variable in Java

For example, I have three classes:
public class A{public static void doSth(){}}
public class B{public static void doSth(){}}
public class C{public static void doSth(){}}
Then I have a variable:
private int controlVariable;
Then based on the value of this controlVariable, I want to invoke the doSth() method in different class above. For example:
switch (i)
{
case 1:
A.doSth();
break;
case 2:
B.doSth();
break;
case 3:
C.doSth();
break;
}
However, using the above approach is very tedious. Can I use a variable to store the name of class. For example:
classNameVariable = A;
classNameVaribale.doSth();
Can anyone help me with this? Please do not use inheritance.
In Java 8 you could use method references:
public class A {
public static void doSth() {
System.out.println("A");
}
}
public class B {
public static void doSth() {
System.out.println("B");
}
}
public class C {
public static void doSth() {
System.out.println("C");
}
}
public class Sample {
public static void main(String[] args) {
Runnable[] methods = { A::doSth, B::doSth, C::doSth };
int controlVariable = 2;
methods[controlVariable].run(); // C
}
}
In this example, controlVariable is a 0-based index.
I believe using A.getClass().getSimpleName() will return a string with the class name as given in the source code.
You can use reflection to get class from class name:
Class cls = Class.forName("your class package");
Method method = cls.getMethod("methodName", arguments);
Object o = method.invoke(null, "whatever");
Hope this will help you.

Pattern of solution for executing and operation that depends upon multiple conditions

Let us say there are 3 operations ops1(), ops2() and ops3(). The client can request to execute any combination of those 3. For e.g.
perform(1): Should execute ops1()
perform(2): Should execute ops2()
perform(1, 2): Should execute ops1() and if ops1() is successful then execute ops2()
perform(1, 2, 3): Should execute ops1() and if ops1() is successful then execute ops2() and if both ops1() and ops2() are successful then execute ops3()
This can go on for n ops() though for me its just 5.
What is the simple and elegant way of implementing this? Is there a pattern for this?
How about you put your ops in a list, look the operations to perform up in that list, and let the operations throw an exception if they fail? Then the perform method can simply try and perform all methods in the desired order until it's done or an exception occurs.
So
private List<Callable> ops;
public void perform(int... opNums) {
try {
for (int i : opNums) {
ops.get(i-1).call();
}
}
catch(Exception ex) {
}
}
I see a solution somewhat like this:
public void perform(int... ops) {
for(int i : ops) {
switch(i) {
case 1:
//...
// if(taskFailed) return;
break;
case 2:
//...
// if(taskFailed) return;
break;
case 3:
//...
// if(taskFailed) return;
break;
// so on for all 5
}
}
}
It's just the general idea, not tested if the syntax is entirely correct.
the "taskFailed" thing is a pseudocode.
An approach for this would be
Define a common interface for opsX methods and the classes that implement this method.
Define an enum to know which class implementation of this common interface should be called.
Define a class that will work as an orchestrator for these calls.
An implementation of this design may be
interface CommonOps {
boolean ops();
}
class Ops1 implements CommonOps {
#Override
public boolean ops() {
//...
}
}
class Ops2 implements CommonOps {
#Override
public boolean ops() {
//...
}
}
//and on...
enum OpsOrder {
OPS1,
OPS2,
OPS3
//... and on
;
}
class Orchestrator {
public boolean executeOps(OpsOrder order) {
switch (order) {
case OPS1:
return new Ops1().ops();
case OPS2:
return new Ops2().ops();
//...
default:
throw new IllegalArgumentException("Not supported.");
}
throw new UnsupportedOperationException("This exception should never be reached.");
}
public boolean orchestrate(OpsOrder ... orders) {
for (OpsOrder order : orders) {
if (!executeOps(orders)) {
return false;
}
}
return true;
}
}
This can be even more generic by having a factory of CommonOps class implementations so Orchestrator should not know which CommonOps will be called:
final class CommonOpsFactory {
private CommonOpsFactory () { }
public static CommonOps create(OpsOrder order) {
switch (order) {
case OPS1:
return new Ops1();
case OPS2:
return new Ops2();
//...
default:
throw new IllegalArgumentException("Not supported.");
}
}
}
class Orchestrator {
public boolean executeOps(OpsOrder order) {
return CommonOpsFactory.create(order).ops();
}
public boolean orchestrate(OpsOrder ... orders) {
for (OpsOrder order : orders) {
if (!executeOps(orders)) {
return false;
}
}
return true;
}
}
I would use the command pattern in combination with the Decorator for this problem. Your commands, when many, will be wrapping/decorating each others :
public class Command{
private Command subCommand;
public Command(Command subCommand){
this.subCommand=subCommand;
}
public Command(){};
public Command addSubCommand(Command command)
{
subCommand=command;
return command;
}
//A Command class is decorating itself
//by adding a behavior over its subcommand
public void execute() throws CommandExecutionException {
executeImpl();
if(subCommand!=null) subCommand.execute();
}
protected void executeImpl() throws CommandExecutionException {
//To be overiden
}
}
public class CommandA extends Command{
private CommandAExecutor ops1Handler;
protected void executeImpl(){
ops1Handler.ops1();
}
}
//....
public class CommandN extends Command{
private CommandNExecutor opsNHandler;
protected void executeImpl(){
opsNHandler.opsN();
}
}
public class Tester{
public static void main(String[] args){
Command commandA = new CommandA(new CommandAExecutor());
Command commandB = new CommandB(new CommandBExecutor());
Command commandN = new CommandN(new CommandNExecutor());
//The order here is A, N, B
commandA.addSubCommand(commandN).addSubCommand(B);
try{
commandA.execute();
}catch(CommandExecutionException e){
//...failure
}
}
}

Categories

Resources