Java 抽象静态解决方法
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1916019/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Java abstract static Workaround
提问by twolfe18
I understand that neither a abstract class nor an interface can contain a method that is both abstract and staticbecause of ambiguity problems, but is there a workaround?
我知道由于歧义问题,抽象类和接口都不能包含既抽象又静态的方法,但是有解决方法吗?
I want to have either an abstract class or an interface that mandates the inclusion of a static method in all of the classes that extend/implement this class/interface. Is there a way to do this in Java? If not, this may be my final straw with Java...
我想要一个抽象类或一个接口,它要求在扩展/实现这个类/接口的所有类中包含一个静态方法。有没有办法在 Java 中做到这一点?如果没有,这可能是我使用 Java 的最后一根稻草......
EDIT 1: The context of this problem is that I have a bunch of classes, call them Stick, Ball, and Toy for now, that have a bunch of entries in a database. I want to create a superclass/interface called Fetchable that requires a static method getFetchables()
in each of the classes below it. The reason the methods in Stick, Ball, and Toy have to be static is because they will be talking to a database to retrieve all of the entries in the database for each class.
编辑 1:这个问题的上下文是我有一堆类,现在称它们为 Stick、Ball 和 Toy,它们在数据库中有一堆条目。我想创建一个名为 Fetchable 的超类/接口,它需要getFetchables()
在它下面的每个类中都有一个静态方法。Stick、Ball 和 Toy 中的方法必须是静态的原因是因为它们将与数据库对话以检索数据库中每个类的所有条目。
EDIT 2: To those who say you cannot do this in any language, that is not true. You can certainly do this in Ruby where class methods are inherited. This is not a case of someone not getting OO, this is a case of missing functionality in the Java language. You can try to argue that you should never need to inherit static (class) methods, but that is utterly wrong and I will ignore any answers that make such points.
编辑 2:对于那些说你不能用任何语言做到这一点的人来说,那不是真的。您当然可以在继承类方法的 Ruby 中执行此操作。这不是某人没有获得 OO 的情况,这是 Java 语言中缺少功能的情况。您可以尝试争辩说您永远不需要继承静态(类)方法,但这是完全错误的,我将忽略任何提出此类观点的答案。
采纳答案by Dave
You have a couple of options:
你有几个选择:
- Use reflection to see if the method exists and then call it.
Create an annotation for the static method named something like @GetAllWidgetsMethod.
As others have said, try to not use a static method.
- 使用反射查看该方法是否存在,然后调用它。
为名为@GetAllWidgetsMethod 之类的静态方法创建一个注释。
正如其他人所说,尽量不要使用静态方法。
回答by Asaph
No. You can't do that. If you're willing to compromise and make the method non-static or provide an implementation of the static method in your abstract class, you'll be able to code this in Java.
不,你不能那样做。如果您愿意妥协并使该方法成为非静态方法或在您的抽象类中提供静态方法的实现,您将能够用 Java 对其进行编码。
回答by GaryF
It doesn't make sense to do what you're asking:
做你要问的事情没有意义:
回答by Michael Borgwardt
Is there a way to do this in Java?
有没有办法在 Java 中做到这一点?
I don't think there is a way to do this in any language. There's no point to it, since static methods belong to a class and can't be called polymorphically. And enabling polymorphic calls is the only reason for interfaces and abstract classes to exist.
我认为没有办法用任何语言来做到这一点。没有意义,因为静态方法属于一个类,不能以多态方式调用。启用多态调用是接口和抽象类存在的唯一原因。
回答by fforw
Create a context interface containing your method with a name that matches your problem domain. (Name it "World" if you absolutely have to, but most of the time there's a better name)
创建一个上下文接口,其中包含您的方法,其名称与您的问题域相匹配。(如果绝对需要,请将其命名为“世界”,但大多数情况下还有更好的名称)
Pass around implementation instances of the context object.
传递上下文对象的实现实例。
回答by twolfe18
Ok, maybe my question was poorly asked, it seems like most of you didn't get what I was trying to do. Nonetheless, I have a solution that is somewhat satisfactory.
好吧,也许我的问题问得不好,似乎你们中的大多数人都没有明白我想要做什么。尽管如此,我有一个有点令人满意的解决方案。
In the abstract super class, I am going to have a static method getAllWidgets(Class type). In it I'll check the class you passed it and do the correct fetching based on that. Generally I like to avoid passing around classes and using switches on stuff like this, but I'll make an exception here.
在抽象超类中,我将有一个静态方法 getAllWidgets(Class type)。在其中,我将检查您传递给它的类,并根据它进行正确的获取。通常我喜欢避免传递类并在这样的东西上使用开关,但我会在这里做一个例外。
回答by Roman
There are lots of answers about 'this does'nt make sense..' but indeed I met a similar problem just yesterday.
有很多关于“这没有意义..”的答案,但我昨天确实遇到了类似的问题。
I wanted to use inheritance with my unit tests. I have an API and several its implementations. So I need only 1 set of unit tests for all implementations but with different setUp methods which are static.
我想在我的单元测试中使用继承。我有一个 API 和几个它的实现。因此,对于所有实现,我只需要 1 组单元测试,但具有不同的静态 setUp 方法。
Workaround: all tests are abstract classes, with some static fields with protected access modifier. In all implementations I added static methods which set these static fields. It works rather nice, and I avoided copy and paste.
解决方法:所有测试都是抽象类,具有一些带有 protected 访问修饰符的静态字段。在所有实现中,我添加了设置这些静态字段的静态方法。它工作得相当好,我避免复制和粘贴。
回答by Douglas Leeder
static methods can't be abstract because they aren't virtual. Therefore anywhere that calls them has to have the concrete type with the implementation. If you want to enforce that all implementations of an interface have a certain static method, then that suggests a unit test is required.
静态方法不能是抽象的,因为它们不是虚拟的。因此,任何调用它们的地方都必须具有实现的具体类型。如果您想强制接口的所有实现都具有某个静态方法,那么这表明需要进行单元测试。
abstract class A
{
public static void foo()
{
java.lang.System.out.println("A::foo");
}
public void bar()
{
java.lang.System.out.println("A::bar");
}
}
class B extends A
{
public static void foo()
{
java.lang.System.out.println("B::foo");
}
public void bar()
{
java.lang.System.out.println("B::bar");
}
}
public class Main
{
public static void main(String[] args)
{
B b = new B();
b.foo();
b.bar();
A a = b;
a.foo();
a.bar();
}
}
回答by irreputable
A type system allows you to express some constraints among types, but it's limited. That's why javadocs are littered with constraints in human language, asking people to follow rules that the compiler cannot check.
类型系统允许您在类型之间表达一些约束,但它是有限的。这就是为什么 javadoc 充斥着人类语言中的约束,要求人们遵循编译器无法检查的规则。
if you want to extend it beyond what language provides natively, you can write your own static analysis tool. that is not uncommon. for example: findbug. also IDEs do that too, they checking thing beyond what language dictates. you can write a plug in to enforce that a subclass must have a static method of such signature.
如果您想将其扩展到语言本身提供的范围之外,您可以编写自己的静态分析工具。这并不少见。例如:findbug。IDE 也这样做,他们检查超出语言要求的事情。您可以编写一个插件来强制子类必须具有此类签名的静态方法。
in your case, it's not worth it. have javadoc in the superclass urge implementors to include a static method, that's good enough.
在你的情况下,这是不值得的。在超类中有 javadoc 敦促实现者包含一个静态方法,这就足够了。
I'll provide a convoluted way of expressing your constraint anyway, but DO NO DO IT. people get really carried away of make everything checkable at compile time, at the price of making code unreadable.
无论如何,我将提供一种复杂的方式来表达您的约束,但不要这样做。人们真的很喜欢在编译时让一切都可以检查,代价是让代码变得不可读。
interface WidgetEnumerator
{
List getAllWidgets();
}
public class Abs<T extends WidgetEnumerator>
{
static List getAllWidgets(Class<? extends Abs> clazz){ ... }
}
public class Sub extends Abs<SubWidgetEnumerator>
{
}
public class SubWidgetEnumerator implements WidgetEnumerator
{
public List getAllWidgets() { ... }
}
How it works: for any subclass of Abs
, it is forced to provide an implementation of WidgetEnumerator. subclass author cannot forget that. Now invocation Abs.getAllWidgets(Sub.class)
contains sufficient information to resolve that implementation, i.e. SubWidgetEnumerator
. It is done through reflection, but it is type safe, there are no string literals involved.
工作原理:对于 的任何子类Abs
,它都被迫提供 WidgetEnumerator 的实现。子类作者不能忘记这一点。现在调用Abs.getAllWidgets(Sub.class)
包含足够的信息来解析该实现,即SubWidgetEnumerator
. 它是通过反射完成的,但它是类型安全的,不涉及字符串文字。
回答by Skip Head
I'd make a WidgetCollection class with an abstract Widget inner class.
我会用一个抽象的 Widget 内部类创建一个 WidgetCollection 类。
You can extend the WidgetCollection.Widget class for each of your types of Widget.
您可以为每种类型的 Widget 扩展 WidgetCollection.Widget 类。
No static methods necessary.
不需要静态方法。
Example (not compiled or tested):
示例(未编译或测试):
class WidgetCollection<W extends Widget> {
Set<W> widgets = new HashSet<W>();
Set<W> getAll() {
return widgets;
}
abstract class Widget {
Widget() {
widgets.add(this);
}
abstract String getName();
}
public static void main(String[] args) {
WidgetCollection<AWidget> aWidgets = new WidgetCollection<AWidget>();
a.new AWidget();
Set<AWidget> widgets = aWidgets.getAll();
}
}
class AWidget extends Widget {
String getName() {
return "AWidget";
}
}