Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Calling method of same name from different class

I have some classes those have methods with same name. For example

public class People {
    private Long id;
    private String nm;
    private String nmBn;
    .............
    public Long getId() {
        return id;
    }

    public String getNm() {
        return nm;
    }

    public String getNmBn() {
        return nmBn;
    }
}

public class Company {
    private Long id;
    private String nm;
    private String nmBn;
    .............
    public Long getId() {
        return id;
    }

    public String getNm() {
        return nm;
    }

    public String getNmBn() {
        return nmBn;
    }
}

Then I need a method that works like:

public String getPeopleString(People people) {
    if (people == null) {
        return "";
    }
    return people.getNmBn() + "|" + people.getNm() + "#" + people.getId();
}

public String getCompanyString(Company company) {
    if (company == null) {
        return "";
    }
    return company.getNmBn() + "|" + company.getNm() + "#" + company.getId();
}

So the methods do same thing but on different type of object.

Is there any way to do this with a single method?

Please note that I can't make any change on People class or in Company class.

like image 876
Md. Shougat Hossain Avatar asked Mar 26 '19 13:03

Md. Shougat Hossain


2 Answers

If the classes do not implement a common interface or extend a common base class - i.e. there is no relationship between the two sets of methods other than the names and signatures - then the only way to accomplish this is via reflection.

String getString(Object companyOrPeople) throws InvocationTargetException, IllegalAccessException
{
    if (companyOrPeople == null) {
        return "";
    }
    final Method getNmBn = companyOrPeople.getClass().getDeclaredMethod("getNmBn");
    final String nmBm = getNmBn.invoke(companyOrPeople).toString();
    // same with the other two methods
    return nmBm + "|" + nm + "#" + id;
}

This is not recommended, however. You lose all compile-time guarantees that these methods actually exist. There is nothing to stop someone passing an Integer or a String or any other type which does not have those getters.

The best thing to do is to change the existing types but if you can't, you can't.

If you do decide to change the existing types then while you're at it do yourself a favour and change the name of the attributes. Because what the hell is a nmBn? Oh, of course, every company has a numbun. How silly of me.

like image 177
Michael Avatar answered Oct 06 '22 18:10

Michael


First, you should create an interface with the common methods, let's call it Identifiable:

public interface Identifiable {

    Long getId();

    String getNm();

    String getNmBn();
}

Ideally, you could make both People and Company implement this interface, but as you said you couldn't modify the existent Company and People classes, you'd then need to extend them, and make the subclasses implement the Identifiable interface:

public PeopleExtended extends People implements Identifiable { }

public CompanyExtended extends Company implements Identifiable { }

Now, simply change the getCompanyString and getPeopleString methods to:

public String getIdString(Identifiable id) {
    return id == null ?
           "" :
           id.getNmBn() + "|" + id.getNm() + "#" + id.getId();
}

And obviously, use the PeopleExtended and CompanyExtended subclasses.

like image 3
fps Avatar answered Oct 06 '22 18:10

fps