java - Java 中的部分重写(或重载时的动态重写)

标签 java dynamic overloading overriding

如果我有一个父子定义了一些方法 .foo() 像这样:

class Parent {
  public void foo(Parent arg) {
    System.out.println("foo in Function");
  }
}
class Child extends Parent {
  public void foo(Child arg) {
    System.out.println("foo in ChildFunction");
  }  
}

当我这样称呼他们时:

  Child f = new Child();
  Parent g = f;
  f.foo(new Parent());
  f.foo(new Child());  
  g.foo(new Parent());
  g.foo(new Child());

输出是:

foo in Parent
foo in Child
foo in Parent
foo in Parent

但是,我想要这个输出:

foo in Parent
foo in Child
foo in Parent
foo in Child

我有一个扩展父类的子类。在 Child 类中,我想“部分覆盖” Parent 的 foo() ,也就是说,如果参数 arg的类型是 Child 然后是 Child's foo()被调用而不是 Parent 的 foo() .

当我打电话 f.foo(...) 时效果很好作为一个 child ;但如果我从它的父别名引用它,就像 g.foo(...) 中那样然后是父级的foo(..)无论 arg 的类型如何,都会被调用。

据我了解,我所期望的事情不会发生,因为Java中的方法重载是早期绑定(bind)(即在编译时静态解析),而方法重写是后期绑定(bind)(即在编译时动态解析)并且因为我使用技术上不同的参数类型定义了一个函数,从技术上讲,我使用不同的定义来重载父级的类定义,而不是覆盖它。但我想做的是在概念上“部分压倒一切”。 foo()的参数是父类 foo() 的子类的论证。

我知道我可以定义存储桶覆盖 foo(Parent arg)在 Child 中检查 arg 的实际类型是 Parent 还是 Child 并正确传递它,但如果我有 20 个 Child,那将是大量重复的类型不安全代码。

在我的实际代码中,Parent 是一个名为“Function”的抽象类,它只是抛出 NotImplementedException() 。子项包括“多项式”、“对数”等,.foo() 包括 Child.add(Child)、Child.intersectionsWith(Child) 等。并非所有 Child.foo(OtherChild) 的组合都是可解的并且在事实上,甚至不是所有的 Child.foo(Child) 都是可以解决的。因此,我最好定义所有未定义的内容(即抛出 NotImplementedException),然后仅定义那些可以定义的内容。

所以问题是:有没有办法只覆盖父级的 foo() 的一部分?或者有更好的方法来做我想做的事吗?

编辑:

@Zeiss:如果我使用双重调度,如下所示:

class Parent {
  public void foo(Parent arg) {
    System.out.println("foo in Parent");
  }
}
class Child extends Parent {
  public void foo(Parent arg) {
    System.out.println("foo in Child(Parent)");
    arg.foo(this);
  }
  public void foo(Child arg) {
    System.out.println("foo in Child(Child)");
  }
}

我得到了无限递归:

(stack): 
StackOverflowError: ...
...
    at sketch_apr25a$Child.foo(sketch_apr25a.java:35)
...
(output):
...
foo in Child(Parent)
...

执行g.foo(new Child());时。其余的似乎都很好,因为输出是:

foo in Child(Parent)
foo in Parent

foo in Child(Child)

foo in Child(Parent)
foo in Parent

foo in Child(Parent)
(infinite recursion follows)

为什么会发生这种情况? g 是 Parent 的别名,但它正在访问 Child 的 foo(Parent)?

最佳答案

这不是 Double Dispatching 的一个用例吗? ?


更新:

class Function {
    public void add(Function f) {
        f.addMe(this);
    }

    public void addMe(Function f) {
        // Default case
        throw NotImplementedException();
    }
    public void addMe(Logarithmic log) {
        // Code that handles the real
    }
}

class Logarithmic extends Function {
    // This object supports adding
    public void add(Function f) {
        f.addMe(this);
    }
}


Logarithmic log = new Logarithmic();
log.add(new Function()); 
log.add(new Logarithmic()); 

Function f = log;
f.add(new Function()); 
f.add(new Logarithmic()); 

关于java - Java 中的部分重写(或重载时的动态重写),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2706258/

相关文章:

java - Handler.handleMessage 在测试中没有被调用,但是在应用中被调用

java - 具有动态 fragment 的 Android 项目在模拟器上崩溃?

java - 如何通过局域网运行swing应用程序的.exe文件?

java - Gradle Uber (Fat) Jar 和运行时中的 java.lang.NoClassDefFoundError

android - 如何在 PhoneGap 中加载动态内容?

linux - .so文件和.a文件的区别?

ruby-on-rails - Rails chart.js 数据 CoffeeScript

c++ - 当类可以转换为函数类型时函数如何重载

c++ - 为什么具有相同名称但不同签名的多重继承函数不被视为重载函数?

c++ - 获取可变数量的参数并将它们放入 std::vector