Better way then If(x instanceof y) in Java? - java

I have those lines of code:
public String getAccountType(BankAccount a){
if(a instanceof RegularAccount)
return "RA";
else if(a instanceof SavingsAccount)
return "SA";
else if(a instanceof cityAccount)
return "CLA";
else if(a instanceof StateLawAccount)
return "SLA";
else if(a instanceof FederationLawAccount)
return "FLA";
else
return null;
}
BankAccount is the super class (abstract) of all classes below. In this method, I just want to return what "a" class is within a String.
But, I was wondering if there is a better way to verify "a" class other than this bunch of if/else statements. Is there one? Could I do it with switch statement? If so, how?

Put an abstract method getAccountType() on BankAccount, and then have the implementations return the account type string. Here's an example that assumes that BankAccount is an interface:
public interface BankAccount {
String getAccountType();
... whatever else ...
}
Then
public class RegularAccount implements BankAccount {
#Override
public String getAccountType() { return "RA"; }
... whatever else ...
}
If BankAccount is a class then just make it an abstract method.

In your case, I'd add an abstract method getAccountType () to the BackAccount class, and implement it in each concrete class so that they return the correct account type.
public abstract class BankAccount {
public abstract String getAccountType ();
// Rest of implementation
}
public class RegularAccount extends BankAccount {
private static final String ACCOUNT_TYPE = "RA";
#Override
public String getACcountType () {
return ACCOUNT_TYPE;
}
// Rest of implementation
}
There is no easier way to compare an object's class than the code example you have provided with your question. However, if you end up having to do this in your code, then you should review your current design.
Consider the case where your manager asks you to add two additional back account types (AccountX and AccountY), and asks you to remove the StateLawAccount (for some reasons). Not only do you have to add the new classes in your code for account types AccountX and AccountY and remove the existing StateLawAccount, but you also have to remember that this unrelated class has this huge if/else that checks for bank account types. If you forget about it, then you have inserted a new bug in your software.

Put a string class member in the abstract class and override its getter method in the implementation to return specific type:
public abstract class BankAccount{
String accountType;
public abstract String getAccountType(){
return accountType;
}
}

Related

Java invoke child method from parent object

I've got next situation:
There is an abstract class
public abstract class SuperClass {
public abstract void getString();
public abstract void method2();
}
public class InheritClass1 extends SuperClass {
#Override
public void getString(){...};
#Override
public void method2(){...};
}
public class InheritClass2 extends SuperClass {
#Override
public void getString{...};
#Override
public void method2(){...};
public void customMethod(){...};
}
There is another class that has a method that accepts SuperClass object as an argument. Depending on what kind of String is returned from getString I perform different actions. My case is that I am trying to call a child method while the object is of parent class:
public class Processor {
public String method(SuperClass type) {
switch (type.getString()) {
case "1":
return "OK"
case "2":
return ((InheritClass2) type).customMethod()
}
}
I do understand that this is BAD DESIGN, could you please help me with finding the best solution for this problem. Maybe generics are suitable in this case somehow. Also the thing is that customMethod() should be a part of not all classes.
Since only some (sub)classes implements customMethod, I would suggest to create an interface that contains this method:
public interface CustomInterface {
public String customMethod();
}
Your SuperClass can then remain just as it is. Only the subclasses/child classes that have customMethod, would then extend your SuperClass as well as implement this CustomInterface. This way, the child classes that do not implement CustomMethod (does not have the method in their class, such as InheritClass1 in your example), also remain just as they are.
Only child classes that have CustomMethod, such as InheritClass2 would then need to change slightly by saying it implements this new interface:
public class InheritClass2 extends SuperClass implements CustomInteface {
// the rest stays the same
}
Then in the section where you want to do the casting, you rather do the following:
public class Processor {
public String method(SuperClass type) {
switch (type.getString()) {
case "1":
return "OK"
case "2":
String s = "";
if (type instance of CustomInterface) {
s = (CustomInterface type).customMethod();
}
return s;
}
}
}
Using the interface in this way will help that you can implement all child classes and not just one as implementing the CustomInterface, and thus, all child classes will work with using instanceof and casting to the interface to call customMethod() - you won't have to handle each child that needs this method separately.
NOTE: Your code is clearly simplified example, it is unclear if the getString() method is just returning an identifier of the child classes in order for you to know which ones you can cast and then call custom Method on... If this is the purpose of your switch and getString methods - to identify which types implement the customMethod() and to call that method, and for any child class that does not have that method to return just "OK" - then you could instead do the following:
public class SubClass1 extends SuperClass implements CustomInterface {
// other mehtods...
public String CustomMethod() { return "SomeString1"; }
}
public class SubClass2 extends SuperClass {
// other methods...
// this subclass does not have the CustomMethod()
}
public class SubClass3 extends SuperClass implements CustomInterface {
// other methods...
public String CustomMethod() { return "SomeString3"; }
}
Then your Processor could look like this:
public class Processor {
public String method(SuperClass type) {
return (type instanceof CustomInterface) ? ((CustomInterface) type).CustomMethod() : "OK";
}
public static void main(String[] args) {
Processor p = new Processor();
SuperClass obj1 = new SubClass1();
SuperClass obj2 = new SubClass2();
SuperClass obj3 = new SubClass3();
System.out.println(p.method(obj1)); // prints: "SomeString1"
System.out.println(p.method(obj2)); // prints: "OK"
System.out.println(p.method(obj3)); // prints: "SomeString3"
}
}
If you don't understand the ternary operator then you can read about it here That's the condition ? exprTrue : exprFalse syntax. It's a short if else statement basically.
You can create an interface, with default custom method implementation, like:
interface A {
default String customMethod() {
return "";
}
}
And abstract class will implement this interface:
public abstract class SupperClass implements A {
public abstract String getString();
public abstract void method2();
}
Bad design will cause you to get bad answers. If you don't want to cast your object to a child object. You could use reflection.
import java.lang.reflect.Method;
public class Processor {
public String method(SuperClass type) {
Method[] methods = type.getClass().getMethods();
for (Method m : methods) {
if (m.getName().equals("customMethod")) {
try {
return m.invoke(type);
} catch (Exception ex) {
// throw
}
}
}
return "OK";
}
}
Depending on your design you could apply:
if (type instanceof InheritClass2.class) return type.customMethod();
or
if (type.getClass() == InheritClass2.class) return type.customMethod();

Reuse validation method. Convert object

I have two similar class objects. I have a couple of methods for the first class object wich I also want to reuse for my second class object but I'm not sure how and I don't want to write duplicate methods.
I extracted and simplified an example to show how i think.
first class
public class FirstClass {
int number;
public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
}
...
}
Second class
public class SecondClass {
int number;
public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
}
...
}
Third class
public class Main {
public static void main(String[] args) {
FirstClass firstClass = new FirstClass();
firstClass.setNumber(5);
SecondClass secondClass = new SecondClass();
secondClass.setNumber(5);
numberIsFive(firstClass);
numberIsFive(secondClass);
}
public void numberIsFive(Object myObject){
if(myObject instanceof FirstClass){
myObject = (FirstClass)myObject;
}else if(myObject instanceof SecondClass){
myObject = (SecondClass)myObject;
}
if(myObject.getNumber() == 5){
System.out.println("is five");
}else{
System.out.println("is not five");
}
...
}
}
and no numberIsIFive(firsclass.getNumber()) is not an option since the methods I use have much more validations.
thanks in advance
For this case that might be "over-engineering", but in general you would look towards composition here, like:
interface IntValueHolder {
int getNumber();
void setNumber(int value);
}
class IntValueHolderImpl implements IntValueHolder { ...
And then you would "drop" the code that you currently have in both of your classes, and instead, both classes would (somehow) have an instance of IntValueHolder.
In your case, it might be more appropriate to simple have your two classes implement that "common" interface IntValueHolder - to at least avoid that repeated instanceof calls and downcast (down to a specific class).
Edit: of course, another option would be to use inheritance here - make your two classes derive from some base class that provides this behavior. But using inheritance just to avoid code duplication is most of the time a bad idea. Classes inherit from each other because that makes "sense" in the underlying model, not to save a line of code.
Before continuing I recommend you to read about it and other object oriented programming concepts by yourself.
Focusing on this particular case, you should create a base class such as
public class BaseClass {
int number;
public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
}
}
Which includes all common fields and methods of your FirstClass and SecondClass. Then remove those methods from your two current classes, and just create them as public class FirstClass extends BaseClass to give them BaseClass functionality.
Finally, you'd have to change your validation method, to only accept objects that belong to your base class by making it like this public void numberIsFive(BaseClass myObject) (as a general rule you'll have much less errors by accepting a specific class in a method, rather than accepting any old object).
Edit: Other answerers are correct and Inheritance is also a valid solution. Which one you use would depend on what makes more sense in the context of your application.
You should create an interface and apply it in both classes, then make your validation method receive an interface instead of an Object
Example:
public interface Number {
int get();
void set(int n);
}
Then your classes will look like this:
public class FirstClass implements Number {
int number;
#Override
public int get() {
return number;
}
#Override
public void set(int n) {
this.number = n;
}
}
And your validation method receives a Number:
public void numberIsFive(Number myNumber){
...
}

How to make Superclass Method returns instance of SubClass

I have a class called Test and a class called SubTest who extends Text, I would like to have a method in the Test class who will returns the instance of SubTest when called, I would like to do :
SubTest test = new SubTest().setTest("Hello!").setOtherTest("Hi!");
The setTest() and setOtherTest() methods should be in the Test class.
But when I do :
public Test setTest(String test) { return this; }
It only returns the instance of Test so I have to cast Test to SubTest, but I don't want to.
Is it possible ? If yes, how ?
Thanks, MinusKube.
Having a method return its owner (this) to be able to 'chain' multiple method calls is called fluent API. You can solve your problem by using generics, although the resulting code might be somehow less readable though:
public class Person<T extends Person<T>> {
public T setName(String name) {
// do anything
return (T)this;
}
}
public class Student extends Person<Student> {
public Student setStudentId(String id) {
// do anything
return this;
}
}
public class Teacher extends Person<Teacher> {
public Teacher setParkingLotId(int id) {
// do anything
return this;
}
}
Now, you do not need any casts:
Student s = new Student().setName("Jessy").setStudentId("1234");
Teacher t = new Teacher().setName("Walter").setParkingLotId(17);
See also: Using Generics To Build Fluent API's In Java
It is possible to have those methods return a SubTest, because Java's return types are covariant.
You must override those methods so that you can return this, a SubTest, in SubTest, e.g.:
#Override
public SubTest setTest(String message) {
super.setTest(message); // same functionality
return this;
}

A java method with both variable return type and variable input arguments

I have an abstract java class "BaseOperation". This class only has a single abstract method:
public abstract T execute()
{
...
return T;
}
Subclasses of BaseOperation must implement this method:
public class GetUsersOperation extends BaseOperation<GetUsersResponse>
{
...
#Override
public GetUsersResponse execute()
{
...
return GetUsersResponse;
}
}
This is a great way to put all common "operation" logic in the BaseOperation class, but still have every concrete subclass's execute() method have a different return type.
Now I need to change this structure to allow the execute() methods to have a variable amount of arguments. For example, one concrete subclass would require:
execute(String, int)
and another would need:
execute(Date, Date, String)
This is tricky, because the execute method is declared in the base class. Simply overloading the execute methods in the base is not ideal. Firstly, the amount of overloads would be huge. Secondly, every subclass will only ever use one of the execute methods, what's the point of all the others?
The (in my opinion) easiest solution would be to declare the execute method with varargs:
execute(Object... arguments)
And then downcast all arguments in the subclasses:
execute(Object... arguments)
{
String s = (String) arguments[0];
...
}
Obviously this has 2 major downsides:
Reduced performance because of all the downcasting operations
Calling the execute() methods is no longer strictly typed because any amount of objects can be passed witout compiler warnings.
Are there patterns or other solutions that could don't have these disadvantages?
You could use a bean holding the parameters:
public interface BaseOperation<T, U> {
T execute(U input);
}
public class GetUsersOperation implements BaseOperation<GetUsersResponse, UserInput> {
#Override
public GetUsersResponse execute(UserInput input) {
Date date = input.getDate();
return new GetUsersResponse(date);
}
}
Your abstract class only has one single abstract method: better use an interface. You can implement several interfaces while you can extend only one class.
As already said, the common approach for solving your issue is using a bean holding parameters. But here is another solution, based on a builder approach:
public interface BaseOperation<T> {
public T execute();
}
public class AddOperation implements BaseOperation<Integer> {
private int a, b;
public void setA(int arg){
a = arg ;
return this;
}
public void setB(int arg){
b = arg;
return this;
}
#Override
public Integer execute() {
return a+b ;
}
}
And then use it like this :
new AddOperation().setA(1).setB(2).execute();
You can mix required and optional parameters in this way:
public class MultipleAddOperation implements BaseOperation<Integer> {
private int sum ;
public MultipleAddOperation(int requiredInt){
sum = requiredInt;
}
public void add(int optionalInt){
sum += optionalInt ;
return this;
}
#Override
public Integer execute(){
return sum;
}
}
And so:
new MultipleAddOperation(5).add(1).add(2).execute();

Should i use instanceof in this scenario or i need to use polymorphism

Suppose I have an Account class,
public class Account {
void Print();
}
and I have derived two subclasses from it i.e. SavingsAccount and CheckingAccount.
public class SavingsAccount extends Account{
void Print();
}
public class CheckingAccount extends Account{
void Print();
}
Now suppose I have a driver class lets say SimulateAccounts which has an array list of type Account,
public class SimulateAccounts{
ArrayList<Node> myAccounts = new ArrayList<Node>();
void simulate()
{ //suppose some function has added added 5 savingAccounts and 10 checkingsAccounts in myAccounts arraylist
}
Now my question is that I want to find the count of the type savingAccounts and checkingAccounts in arraylist myAccounts in the above function of simulate, I can do this by using instanceof function. But I am confused over using it as I have read on numerous places that using instanceof is bad practice and code smell, so how can I fit polymorphism into it to avoid using instanceof or is it ok to use. Moreover if I use instance of and in future name of savingsAccount changes I need to also update my this code in simulation function! So what should I do here.
Thanks
If you're using C# (your naming conventions indicate both Java and C#), you can just use .OfType<CheckingAccount>().Count.
But sure, go ahead and use instanceof. This isn't why it should be used with caution, it's when you define subclass-specific behaviour without providing an implementation in the class itself.
For example:
if(account instanceof CheckingAccount)
{
// Do something
} else if(account instanceof SavingsAccount) {
// Do another thing
}
As opposed to
account.DoAccountTypeSpecificThing();
What you want to do makes sense.
You could use enum to avoid instanceof:
public enum AccountType
{
Check, Saving
}
public class Account
{
void Print();
AccountType getAccountType();
}
public class SavingsAccount extends Account
{
void Print(){};
AccountType getAccountType()
{
return AccountType.Saving;
}
}
public class CheckingAccount extends Account
{
void Print(){};
AccountType getAccountType()
{
return AccountType.Check;
}
}
Now, if you want to know the type of an Account instance:
Account a = ...
switch(a.getAccountType())
{
case Check:
// do something specific to checking account
break;
case Saving:
//do something specific to saving account
break;
default:
break;
}
BTW, the use of extends to inherits classes is even worse than using instanceof in my opinion.

Categories