简体   繁体   中英

Generic method for not related objects - java

I have following two classes:

public Class A{
    String name;
    Integer age;

    //setters and getters
}

And

public Class B{
    String name;
    Integer age;
    Integer height;

    //setters and getters
}

and following method

public String getMyName(B b){
    return b.getName()+" "+b.getAge()+" "+b.getHeight();
}

Is it possible to refactor this method to use generics which will allow me to call it for objects of those two different classes?

Eg

public <T> String getMyName(T t){
    return t.getName()+" "+t.getAge()+( t instanceof B ? " "+t.getHeight() : "");
}

Of course it doesn't work since t doesn't know methods getName , getAge and getHeight .

Classes are not in any relation( I know that they can inherit from one common class and use <T extends C> but they don't have superclass or common interface)

No, without using a common interface or superclass this is not possible with generics. You could use reflection but I'd advice against that and suggest providing a common interface instead.

As others said, there would be other ways to handle that case (eg method overloading or passing Object and using instanceof and casts) but if you can use a common interface, I'd still go that way.

Note that Java generics are unlinke C++ generics/templates which would allow what you want to do - and there are good reasons for that difference.

This is the place where people shout the line Programming with interfaces .

Take a an interface and add common methods to it and create a generic method which takes that interface as a argument.

That makes your life easy.

You can use instanceof to check whether is compatible type and if it is, cast object to your type and call methods. It is not elegant way, but still. So this way, you can use your method as generic. :)

You can dynamically adapt them on the fly - something like:

public class A {

    String name;
    Integer age;

    public String getName() {
        return name;
    }

    public Integer getAge() {
        return age;
    }
}

public class B {

    String name;
    Integer age;
    Integer height;

    public String getName() {
        return name;
    }

    public Integer getAge() {
        return age;
    }

    public Integer getHeight() {
        return height;
    }
}

// Create a common interface.
public interface AorB {

    public String getName();

    public Integer getAge();

    // Use Java 8 to implant a default getHeight if it is missing.
    default Integer getHeight() {
        return 0;
    }
}

// Dynamicaly adapt each type.
public String getMyName(A a) {
    // Adapt it on the fly.
    return getMyName(new AorB() {

        @Override
        public String getName() {
            return a.getName();
        }

        @Override
        public Integer getAge() {
            return a.getAge();
        }

    });
}

public String getMyName(B b) {
    // Adapt it on the fly.
    return getMyName(new AorB() {

        @Override
        public String getName() {
            return b.getName();
        }

        @Override
        public Integer getAge() {
            return b.getAge();
        }

        @Override
        public Integer getHeight() {
            return b.getHeight();
        }

    });
}

// Your method almost untouched.
public String getMyName(AorB ab) {
    return ab.getName() + " " + ab.getAge() + " " + ab.getHeight();
}

public void test() {
    A a = new A();
    a.name = "A";
    a.age = 10;

    B b = new B();
    b.name = "B";
    b.age = 10;
    b.height = 12;

    System.out.println("A:" + getMyName(a));
    System.out.println("B:" + getMyName(b));
}

I am using Java-8 default here to implement a default getHeight but it would not take much effort to eliminate that - you would need to implement a getHeight for the getMyName(A) method.

Sadly - of course - this is not using generics in the solution so you may see this as not an answer to your question but it is an alternate solution to your problem so I chose to post.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM