Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Call a method based on the object type

I have two helper methods:

public String load(URL url) {...}
public String load(File file) {...}

I want to have a method that calls the appropriate helper method depending on what object type it receives:

public void operate(Object object) {...}

I understand that there is a convoluted way of doing it which is:

public void operate(Object object) {
    String data = null;
    if (object.getClass().equals(File.class)) {
        data = load((File) object);
    }
    if (object.getClass().equals(URL.class)) {
        data = load((URL) object);
    }
    // operate on the data....
}

However, this does not seem elegant and was curious if there was a better way..

like image 468
Brian Risk Avatar asked Jul 16 '15 15:07

Brian Risk


People also ask

How do you call a method from an object?

To call an object's method, simply append the method name to an object reference with an intervening '. ' (period), and provide any arguments to the method within enclosing parentheses. If the method does not require any arguments, just use empty parentheses.

How do you call a method from an object in Java?

The dot ( . ) is used to access the object's attributes and methods. To call a method in Java, write the method name followed by a set of parentheses (), followed by a semicolon ( ; ).

What does it mean to call a method on an object?

Methods of an object are called to make it do something. Calling a method in an object also makes use of dot notation. The object whose method is being called is on the left side of the dot, and the name of the method and its arguments are on the right side: customer. addToCart(itemNumber, price, quantity);

Can a class method be called on an object?

You have to call with an object. If the method is static the object can be the class.


2 Answers

However, this does not seem elegant and was curious if there was a better way.

That's right. This violates the Open-Closed principle. A class must be open to extension but closed to modification. You are also correct when you say that you need a generic Object. Here's what you can do :

Create a Loader interface

public interface Loader<T> {
   public String load(T t);
}

Create a loader for loading from File

public class FileLoader implements Loader<File> {
     public String load(File f) { 
            //load from file 
     }    
}

Create a loader for loading from Url

public class UrlLoader implements Loader<Url> {
     public String load(URL r) { 
            //load from url 
     }    
}

Create a class that operates on the data

 class DataOperator<T> {
    Loader<T> loader;
    public SomeClient(Loader<T> loader) {
       this.loader = loader;
    }

    public void operate(T inputSource) {
       String data = loader.load(inputSource);
       //operate on the data
    }

 }

Client code can then use the above API as shown below :

DataOperator<File> fileDataOperator = new DataOperator<>(new FileLoader());
fileDataOperator.operate(new File("somefile.txt"));

DataOperator<URL> urlDataOperator = new DataOperator<>(new UrlLoader());
urlDataOperator.operate(new URL("http://somesite.com")); 

You might be thinking that this is a lot of classes for solving a simple problem. However, this is actually inline with the well known Open-Closed design principle. Notice how you control what technique is used for loading the data by creating an instance of an appropriate class. Another advantage you get is that you can decide which technique to use at runtime by creating a Factory that takes user input and creates the appropriate concrete subclass. This is a simplified version of the Strategy pattern.

Disclaimer : The code samples presented above have not been tested for compilation errors as I don't have Java on this machine.

like image 140
Chetan Kinger Avatar answered Nov 14 '22 20:11

Chetan Kinger


A slightly less convoluted way is instanceof, e.g.

if (object instanceof File)) {
    data = load((File) object);
}

However, most of the time, using instanceof is a sign that there's a better structure for what you're trying to achieve, e.g.

public void operate(File file) {
    operate(load(file));
}

public void operate(URL url) {
    operate(load(url));
}

public void operate(String data) {
    // operate on the data....
}
like image 21
CupawnTae Avatar answered Nov 14 '22 22:11

CupawnTae