【问题标题】:how to call method without knowing the class name?如何在不知道类名的情况下调用方法?
【发布时间】:2010-01-04 16:14:49
【问题描述】:

我在下面定义了两个类:

public class junk {
   private BigInteger a = BigIngeger.valueOf(1), b=BigInteger.valueOf(2), c;

   public void DoSomething() {
      c = a.add(b);
   }

   // ... other stuff here
}

public class junkChild extends junk {
   private BigDecimal a = BigDecimal.valueOf(1), b=BigDecimal.valueOf(2), c;
   // I want a, b, c to override the original BigInteger a,b,c 
   // ... other stuff here
}     

public class myClass {
   public static void main(String args[]) {
      junk a1 = new junkChild();
      a1.DoSomething();
   }
}

不幸的是,上述方法不起作用。

我想要做的只是将junkChild 中的abc 更改为BigDecimal,而无需再次重写DoSomething()。即使我必须再次编写它,代码也会完全一样,所以应该有一种方法可以让我无需编写它就可以完成这项工作。 DoSomething 函数应该检查 a1 类型是否具有正确输入和返回类型的 add 方法,如果是,则调用它而不必担心 abc 的类型是。

这个可以吗?

【问题讨论】:

  • 你应该阅读反思。它将满足您问题的第二部分。至于第一部分,不要直接使用字段abc,而是使用您在子类中覆盖的方法getAgetBgetC
  • 听起来您真正想要的是类 C++ 模板。
  • 听起来他真正想要的是“鸭子打字”。
  • ok 反射似乎可以让我为所欲为。顺便说一句,我想我可以重载字段如下junk xyz; xyz = new junkChild();
  • 太糟糕了。 不要使用反射来解决这个问题。这是一个的解决方案。您原来的包装方法解决方案更加更干净。

标签: java class field overloading anonymous


【解决方案1】:

不,你不能这样做——至少在编译时不能。这两个add 方法实际上是不相关的——它们不是来自接口或类似的东西。

您可以通过反射来实现(在为abc 或类似的东西添加属性之后 - 字段不能像这样“覆盖”),但它不会非常好。

【讨论】:

  • 最中肯的答案。出于好奇,为什么可以用System.out.print 做到这一点? (我们可以为任意类定义一个toString 方法)
  • @Jus12: toString() 继承自 Object,所有类最终都继承自 Object。任何类都可以覆盖toString()
【解决方案2】:

您询问的编程语言功能称为duck typing,Java 不支持它。你必须坚持原来的包装方法策略。

【讨论】:

    【解决方案3】:

    如前所述,Java 不会在两种类型不共享有用接口的情况下进行“鸭式打字”。 BigDecimal 和 BigInteger 都扩展了 Number,但 add() 方法不是该接口的一部分,所以它没有帮助。

    我认为您需要在 doSomething() 的方法参数中明确说明您正在操作的内容。然后您可以覆盖 doSomething() 以对这两种类型进行操作:

    public BigDecimal doSomething(BigDecimal a, BigDecimal b) {
            return a.add( b );
    }
    
    public BigInteger doSomething(BigInteger a, BigInteger b) {
        BigDecimal x = new BigDecimal(a);
        BigDecimal y = new BigDecimal(b);
        BigDecimal z = doSomething(x, y);
        return z.toBigInteger();
    }
    

    第二种方法只是一个转换方法,然后在第一种方法中调用真正的逻辑。

    【讨论】:

    • 从那以后我搬到了 Scala。在 Scala 中,这些事情非常简单def foo[T <: {def add[T](a:T, b:T):Unit;val a:T}] (bar:T):T = ???
    【解决方案4】:

    由于 Number(两个类的最近祖先没有 add 方法),您可以先将 BigInteger 转换为 BigDecimal:

    new BigDecimal(bi)
    

    【讨论】:

      猜你喜欢
      • 2016-10-01
      • 2013-05-21
      • 1970-01-01
      • 2016-07-19
      • 1970-01-01
      • 2017-12-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多