简体   繁体   中英

accessing methods of a class through generic Object type

I am fairly new to java, I was primarily a PHP/JavaScript developer for years. I have now been tasked with rewriting one of my PHP applications in java and I am stuck on a part that is driving me nuts. A quick overview of the problem: I have 2 different types of "reply" objects, I am creating a class that accepts both of them. I then need to be able to loop through them and check a method in them. Hard to explain, but I will give an extremely simplified version in code...

public class A {

    private Boolean success;
    private Map<String, ? extends Object> prop;

    public A() {}

    public boolean getSuccess() {
        boolean succeed = true;
        for(Map.Entry<String, ? extends Object> result : prop.entrySet()) {
            String type = result.getKey();
            Object response = result.getValue();
            //I need to access the method getSuccess() in  AResult or BResult here, but cannot. Why? and How?
            /*
            if(!response.getSuccess()) {
                succeed = false;    
            }*/
        }
        return succeed;
    }

    public void addResult(String type, BResult result) {
        prop.add(type, result);
    }

    public void addResult(String type, AResult result) {
        prop.add(type, result);
    }
}

public class AResult {

    private Boolean success;
    private String type;

    public AResult(String type, Boolean success) {
        this.type = type;
        this.success = success;
    }

    public boolean getSuccess() {
        return success;
    }
    public void setSuccess(Boolean success) {
        this.success = success;
    }
    public String getType() {
        return type;
    }
    public void setType(String type) {
        this.type = type;
    }
}

public class BResult {

    private Boolean success;
    private String type;

    public BResult(String type, Boolean success) {
        this.type = type;
        this.success = success;
    }
    public boolean getSuccess() {
        return success;
    }
    public void setSuccess(Boolean success) {
        this.success = success;
    }
    public String getType() {
        return type;
    }
    public void setType(String type) {
        this.type = type;
    }
}

Now, given the following how can I access the .getSuccess() of each result type inside of the loop in A?

A me = new A();
me.addResult(new AResult("rate", true));
me.addResult(new BResult("label", false));
if(me.getSuccess()) {
    //yay things went well;
} else {
    //boo things went bad;
}

I absolutely have to have Aresult and BResult, that I cannot change. In the getSuccess() method of A it will not allow me access getSuccess() of the AResult and BResult classes, and I can't force a type on it because it could be either AResult or BResult.

I thought about trying something like....

if(response instaceof AResult) { 
    AResult res = (AResult) result; 
    //...
} else if(response instanceof BResult) {
    BResult res = (BResult) result;
    //...
}

but if we ever decide to add a new type, like CResult or whatever it would render that code unusable and I could end up with a giant mess of if elseif statements trying to determine the correct type just to access a simgle method inside of it. I am seriously lost on this one, any help anyone could provide would be greatly appreciated. Thank you so much for your time.

1. Create an interface:

interface Result {
    boolean getSuccess();
}

2. Implement it in AResult and BResult :

public class AResult implements Result {
    // ...

3. Make prop a Map<String, Result>

Now, you can use Result as the type of the things in prop , and since Result has getSuccess , you can use it.

You might use a base class that AResult and BResult extend , rather than an interface; or you might choose to use both for maximum flexibility, where the base class implements Result but is abstract .

Fundamentally:

  1. If things have common characteristics, create an interface for those characteristics.

  2. If you want to share the implementation of those common characteristics, either:

    • Use a base class that the classes extend (inheritance)

    • Isolate those characteristics into their own classes, and then use those classes within AResult and BResult (this is called composition or aggregation )

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