【问题标题】:Java invoke child method from parent objectJava 从父对象调用子方法
【发布时间】:2018-04-09 06:58:24
【问题描述】:

我有下一个情况:

有一个抽象类

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 返回的字符串类型,我执行不同的操作。我的情况是我试图在对象属于父类时调用子方法:

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

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

【问题讨论】:

  • 添加非抽象 customMethod() 对您的父类没有任何作用,仅在需要时覆盖它..
  • 为什么不将customMethod 拉到父级,默认实现为return "OK";?然后,子实现可以进行getString 检查,它仍然需要
  • 你的 getString() 方法声明应该返回一个字符串而不是 void。
  • 注意,如果您希望 Processor 类中的 method() 编译,getString() 和 cutsomMethod() 的返回类型应为 String,因为此方法返回 String 值.

标签: java generics inheritance polymorphism


【解决方案1】:

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

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

或

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

【讨论】:

  • 这会更糟
【解决方案2】:

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

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

而抽象类会实现这个接口:

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

【讨论】:

    【解决方案3】:

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

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

    【讨论】:

    • 如果一个类有很多方法,这可能有点过分和计算量大...可能使用接口并检查孩子是否实现了接口,如果没有则返回“OK “.. 一个 if 语句与所有反射调用以及迭代所有现有方法相比 - 这是 n 阶复杂度,取决于方法的数量。
    • 我同意,我只提供了这个答案,因为 OP 已经拒绝检查该类是否是一个实例。
    • 好点 :) 如果检查类的实例完全不是一种选择,那么这 is 是一个(计算效率低下的)解决方案。 (一点注意:被拒绝的版本正在检查特定的子类类型,而不是对具有该方法的所有子类通用;但我可能错了 - OP 可能根本不想使用 instanceof -那么这个解决方案就可以解决这个问题。)
    【解决方案4】:

    由于只有一些(子)类实现了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并转换为调用@的接口987654336@ - 您不必单独处理需要此方法的每个孩子。


    注意:您的代码显然是简化的示例,尚不清楚 getString() 方法是否只是返回子类的标识符,以便您知道可以转换哪些子类,然后调用自定义方法...如果这是您的 switch 和 getString 方法的目的 - 确定哪些类型实现了 customMethod() 并调用该方法,并且对于没有该方法的任何子类只返回“OK” - 那么你可以而是执行以下操作:

    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 语句。

    【讨论】:

      猜你喜欢
      • 2011-04-17
      • 2012-07-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-10-11
      • 1970-01-01
      相关资源
      最近更新 更多