【问题标题】:Java: static method in abstract class call abstract non-static method?Java:抽象类中的静态方法调用抽象非静态方法?
【发布时间】:2012-12-03 08:25:14
【问题描述】:

我有一个抽象类 A

我有大约 10 个扩展 A 的类

A 类有一个或两个静态方法,它们是静态的是有道理的,因为它们属于 10 个类,而不是它们的实例。一种静态方法,例如被称为 getAllFromX,它从 X 中获取类的所有实例,无论它是什么,它可能是一个服务器,实际上它是,但没关系。所以你会发现这些方法是静态的并且不绑定到实例是有道理的。

同时A类有一个非静态抽象方法,每个子类都覆盖这个方法(只返回一个字符串)。我无法将其设为静态,因为无法覆盖静态方法 (...)。

总结一下:抽象类 A 有一个静态方法和一个抽象非静态方法,它被子类覆盖。我不能将第二种方法设为静态,因为它必须被覆盖。另一方面,我可以将第一个方法设置为非静态的,但它会非常丑陋和糟糕的编程风格,所以我将保持这种方式。

捕获?类 A 中的静态方法必须获取非静态方法返回的值(对于继承静态方法的子类,当然)。

使用反射来完成这项工作是“最简单”的方式吗?我是说……真的吗?

例如,我得到了静态方法所在的类:

Class<?> cl=new Object(){}.getClass().getEnclosingClass(); (a hack I found here, thank god...)

然后我使用 getConstructor 来构造这个子类的一个对象。

然后我用这个对象调用非静态方法。

真的吗??难道不能更容易吗?我的意思是,如果我想设计我的程序在概念上是正确的......

来自 C# 我不喜欢那样(以及类型擦除)。这很丑陋。可行但丑陋。和一个很大的绊脚石,至少对于初学者来说。编辑:再次阅读后,我会添加:/rant end。对不起,但我真的很在乎。

【问题讨论】:

  • 在没有任何实例可以调用实例方法的情况下,从静态方法调用非静态方法是没有意义的。向我们说明您希望使用这些方法实现什么目标,我们可能会找到解决方案。
  • 你说的都是对的。 @JB 这是很好的 Java 设计,与 C# 相同。这就是为什么我希望非静态方法是静态的。但是在Java中我不能覆盖静态。这不是好的 Java 设计。不仅可以在类级别上覆盖实例级别。
  • 您不能覆盖静态方法,因为它们不是继承的。如果你打电话给SubClassOfA.theStaticMethod(),你实际上是在打电话给A.theStaticMethod()。编译器允许你这样调用它,但生成的字节码是:A.theStaticMethod()。如果你希望每个子类都有自己的静态方法,那么你必须将它添加到每个子类中,然后你将隐藏 A 中定义的静态方法。
  • 好的,谢谢,我不知道那一点语法糖。

标签: java methods static instance


【解决方案1】:

我认为您的问题是更大的设计之一。一个不同的对象应该负责检索 A 或其子类的实例。如您所见,依靠静态方法被子类替换并不能很好地工作。在不了解问题域的情况下,很难给出一个好的答案,但我会考虑类似于抽象工厂模式的东西。

广义地说:定义一个抽象类,AFactory,使用方法 Collection getInstances()。为 A 的每个具体子类扩展 AFactory ,您需要在重写的 getInstances() 方法中适当地返回并实现该逻辑。您还可以在抽象 AFactory 上提供静态方法 getFactory(Class),以在运行时获取适当的工厂子类型。

【讨论】:

    【解决方案2】:

    我认为您实际上需要的是以下内容:

    public class A {
        public static Set<A> getAllFromX() {
            ...
        }
    }
    
    public class B extends A {
        public static Set<B> getAllFromX() {
            ...
        }
    }
    
    
    public class C extends A {
        public static Set<C> getAllFromX() {
            ...
        }
    }
    

    (就像枚举中的valueOf()values()方法一样,在每个Enum子类中都会重新定义,因为静态方法不能被继承)

    在这种情况下,每个类都有自己的静态方法,可以随心所欲。但是你的问题没有多大意义,因为它说:

    类 A 中的静态方法必须获取非静态方法返回的值(对于继承静态方法的子类,当然)。

    确实,静态方法被子类继承。静态方法永远不会被继承。如果你在A中定义了一个静态方法foo(),然后调用

    B.foo();
    

    编译器不会拒绝编译它,而是将它翻译成

    A.foo();
    

    因此,在 foo() 中没有办法做取决于调用 foo() 的类的事情,因为它始终是 A。

    【讨论】:

      【解决方案3】:

      您总是可以使用反射来调用使用类名的方法,例如

          Object objectX = ClassX.class.newInstance();
          //get your method passing argument types as second param
          Method method = ClassX.class.getDeclaredMethod("methodX", null);
          //invoke your method passing arguments as second param
          method.invoke(objectX, null);
      

      由于您提到您的静态方法不使用任何实例,但您使用反射来获取实例,因此我真的不确定,它如何满足您的要求。

      我认为将其作为抽象类中的实现方法(非静态)是一个更好的选择。这样您只实现一次,但它在所有 10 个扩展类中都可用。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-09-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-03-19
        相关资源
        最近更新 更多