Java从父对象调用子方法

时间:2017-10-27 15:50:04

标签: java generics inheritance polymorphism

我有下一个情况:

有一个抽象类

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(){...};
}

还有另一个类有一个接受SuperClass对象作为参数的方法。根据getString返回的String类型,我执行不同的操作。我的情况是我试图在对象是父类时调用子方法:

public class Processor {
    public String method(SuperClass type) {
         switch (type.getString()) {
             case "1":
               return "OK"
             case "2":
               return ((InheritClass2) type).customMethod()
         }
 }

我明白这是糟糕的设计,请你帮我找到解决这个问题的最佳解决方案。也许泛型在某种程度上适合这种情况。另外,问题是customMethod()应​​该是并非所有类的一部分。

4 个答案:

答案 0 :(得分:1)

根据您的设计,您可以申请:

if (type instanceof InheritClass2.class) return type.customMethod();

if (type.getClass() == InheritClass2.class) return type.customMethod();

答案 1 :(得分:1)

由于只有一些(子)类实现customMethod,我建议创建一个包含此方法的接口:

public interface CustomInterface {
    public String customMethod();
}

您的SuperClass可以保持原样。只有具有customMethod的子类/子类才会扩展您的SuperClass以及实现此CustomInterface。这样,未实现CustomMethod的子类(在其类中没有方法,例如示例中的InheritClass1)也保持原样。

只有具有CustomMethod的子类,例如InheritClass2才需要稍微改变,因为它说它实现了这个新接口:

public class InheritClass2 extends SuperClass implements CustomInteface {
    // the rest stays the same
}

然后,在您要进行投射的部分中,您需要执行以下操作:

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;
        }
    }
}

以这种方式使用接口将有助于您实现所有子类而不仅仅是实现CustomInterface的子类,因此,所有子类都可以使用instanceof并转换为调用customMethod()的界面 - 您不必单独处理需要此方法的每个孩子。

注意:您的代码是明显简化的示例,不清楚getString()方法是否只返回子类的标识符,以便您知道可以投射哪些,然后调用自定义方法。 ..如果这是您的切换和getString方法的目的 - 识别哪些类型实现customMethod()并调用该方法,以及任何没有该方法的子类只返回“好的“ - 然后你可以改为:

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"; }
}

然后你的处理器看起来像这样:

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"
    }
}

如果您不理解三元运算符,那么您可以阅读它here这就是condition ? exprTrue : exprFalse语法。这基本上是一个简短的if else语句。

答案 2 :(得分:0)

您可以使用默认的自定义方法实现创建一个接口,例如:

interface A {
    default String customMethod() {
        return "";
    }
}

抽象类将实现此接口:

public abstract class SupperClass implements A {
    public abstract String getString();
    public abstract void method2();
}

答案 3 :(得分:0)

糟糕的设计会让你得到错误的答案。如果您不想将对象转换为子对象。你可以使用反射。

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";
    }
}