【问题标题】:Calling method that exists in child classes but not in parent class调用子类中存在但父类中不存在的方法
【发布时间】:2018-11-24 20:08:36
【问题描述】:
public class Parent {
    ....
}

public class Child1 extends Parent {
    ....
    public void foo() {
        ....
    }
}

public class Child2 extends Parent {
    ....
    public void foo() {
        ....
    }
}

这里的方法foo() 只存在于子类中,不能添加到父类中(甚至不能添加抽象方法)。在这种情况下,当我想在obj 上调用foo() 方法时,这是Parent 类的引用,那么我需要使用intanceof 和多个我想避免的if..else

Parent obj = ...// Object of one of the child classes
obj.foo();

编辑:我只需要将obj 类型用作Parent。否则我将无法调用父类中存在的 obj 上的方法。


我的解决方案:我正在考虑的方法是定义一个接口说FooInterfacefoo() 方法并让所有子类实现它,然后我可以只键入转换@ 987654333@ 到该接口并像这样调用 foo() 方法:

if(obj instanceof FooInterface){
    ((FooInterface)obj).foo();
}

有没有更好的方法?或者对这个有什么改进?

【问题讨论】:

  • 当一个方法在子节点中很常见时,它应该放在父节点中。为什么你不把那个方法放在抽象类中??
  • 我无法更改 Parent 课程,因为我无法管理它。
  • 然后使用下面答案中给出的解决方案中说明的界面。
  • 能介绍一下Parent和Child的中间类吗?

标签: java oop class-design instanceof


【解决方案1】:

多态性应用于对象引用,而不是类型。当你打电话时

FooInterface obj = ...// Object of one of the child classes
obj.foo(); 

子类方法foo()被调用。

【讨论】:

  • 再看OP问题。 Parent 没有任何 foo() 方法。
  • 如何在接口没有声明该方法的接口引用上调用方法?看我的帖子。
  • @Braj 现在你应该再次阅读 OP 问题,接口定义了一个方法 foo。
  • @Learner 对您的另一条评论,在设计您的类时,请考虑对接口进行编码,而不是类。
  • @RomanC,使用此解决方案,我将无法调用存在于 Parent 类中的 obj 上的方法。是的,我了解接口代码的优势,但这是遗留代码,我不能修改 Parent 类。
【解决方案2】:

如果您只想进行类型转换,则无需添加接口。您可以将其类型转换为所需的类并调用该方法。示例

public class HelloWorld {
    public static void main(String args[]) throws FileNotFoundException {
        SuperClass sc =new Child1();
        if(sc instanceof Child1)//Do same for Child2
        ((Child1)sc).foo();
    }
}

class SuperClass {

}

class Child1 extends SuperClass{
    public void foo(){
        System.out.println("From child1");
    }
}

class Child2 extends SuperClass{
    public void foo(){
        System.out.println("From child2");
    }
}

输出: 来自child1

【讨论】:

  • 好吧,我认为这不是一个好方法,因此不想使用它。如果有多个子类,那将是丑陋的。不是吗?
【解决方案3】:

除非在父类/接口本身中声明了一个除非方法,否则您不能对父对象引用执行此操作。

您必须将其向下转换为子类,因为父类/接口除了它们之间定义的合同之外,对子类一无所知。

这里contract 表示abstract methods


你可以在不需要勾选的地方尝试这种方式。

FooInterface sc =new Child1();
sc.foo();

...

interface FooInterface{
    void foo();
}

public class Parent {

}

public class Child1 extends Parent implements FooInterface{

    public void foo() {

    }
}

public class Child2 extends Parent implements FooInterface{

    public void foo() {

    }
}

【讨论】:

  • 使用此解决方案,我将无法调用父类中存在的sc 上的方法。我编辑了我的问题以提及这一点。谢谢。
  • 你是否让Child1 实现FooInterfaceChild2 相同?
  • 这是我在我的解决方案中提到的,唯一的区别是在我的解决方案中,引用的类型是 Parent,因此我需要使用一次 instanceof 来查看它是否是 @ 类型987654330@.
  • 所以你不想改变你的设计那么它是不可能的,因为我告诉你父类/接口对子类没有任何知识。怎么会父类/接口知道孩子创建了 x 个方法吗?
  • 我在问题中提到的解决方案怎么样?它确实解决了我的问题。但好的方法是我想知道的吗?
【解决方案4】:

您可以实现一个从Parent 继承的AbstractChild,然后扩展这个类而不是Parent

public class Parent {
    ....
}

public abstract class AbstractChild extends Parent{

    public abstract void foo();

}



public class Child1 extends AbstractChild {
    ....
    public void foo() {
        ....
    }
}

public class Child2 extends AbstractChild {
    ....
    public void foo() {
        ....
    }
}

所以您只需检查您的实例是否为instanceof AbstractChild

【讨论】:

    【解决方案5】:

    我最终采用的方法是使用foo() 方法定义一个接口FooInterface 并让所有子类实现它,然后我可以将obj 类型转换为该接口并调用foo() 方法像这样:

    Parent obj = ...// Object of one of the child classes
    .....
    if(obj instanceof FooInterface){
        ((FooInterface)obj).foo();
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-02-14
      • 2017-07-22
      • 1970-01-01
      • 1970-01-01
      • 2019-06-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多