2

我有一个抽象类 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。对不起,但我真的很在乎。

4

3 回答 3

1

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

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()andvalues()方法一样,在每个 Enum 子类中都会重新定义,因为静态方法不能被继承)

在这种情况下,每个类都有自己的静态方法来做任何事情。但是您的问题没有多大意义,因为它说:

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

事实上,静态方法不会被子类继承。静态方法永远不会被继承。如果foo()在 A 中定义一个静态方法,并调用

B.foo();

编译器不会拒绝编译它,而是将其转换为

A.foo();

所以,没有办法做foo()依赖于foo()被调用的类的事情,因为它总是 A。

于 2012-12-15T16:34:52.293 回答
0

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

    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 个扩展类中都可用。

于 2012-12-15T16:22:09.097 回答
0

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

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

于 2012-12-15T16:42:35.417 回答