为什么实现类不能将重写的方法定义为静态的?

3

我很困惑为什么以下内容不被允许:

public interface MyInterface {
  MyInterface getInstance(String name);
}

public class MyImplementation implements MyInterface {
  public MyImplementation(String name) {
  }
  @Override
  public static MyInterface getInstance(String name) { // static is not allowed here
    return new MyImplementation(name)
  }
}

我理解为什么接口中的方法不能是静态的,但为什么覆盖该方法的方法不能是静态的呢?
我希望所有类都实现getInstance(String name)方法,但目前只能在已经实例化对象的情况下调用该方法,这有点违背初衷...
更新:谢谢回答,我现在更好地理解了。基本上我不应该试图让一个实用类(或工厂类)实现一个接口(或至少不是这种方式)...

想一想,你会如何称呼一个被覆盖的静态方法? - biziclop
1
@TedHopp 从技术上讲,这恰恰相反于那个问题。 - biziclop
这不是关于接口方法是静态的,而是允许我使实现方法成为静态的。因此,我可以调用MyImplementation.getInstance("foo");而不是new MyInterface("foo").getInstance("foo"); - KidTempo
你正在尝试进行不符合规范的继承和静态方法。Java是否支持不符合规范的继承? - ctrl-alt-delor
2
请注意,在您的示例中,静态覆盖的签名与接口方法的签名不匹配。这甚至不是一个有效的覆盖。 - Tudor
4个回答

9
在Java中调用静态方法需要指定确切的类型。无法通过多态方式调用静态方法,从而消除了使用@Override的必要性。
请注意,这种方法并不适用于所有语言:例如,您可以在Objective-C中重写类方法,并且苹果的Cocoa框架充分利用了这个机制来自定义其“工厂”类。但是,在Java、C++和C#中,类方法不支持多态行为。
理论上,Java设计者可以让你通过静态方法提供接口方法实现,以防实现不需要访问实例状态。但使用简单的包装器可以轻松实现相同的行为:
public class MyImplementation implements MyInterface {
    public MyImplementation(String name) {
    }
    @Override
    public MyInterface getInstance() { // static is not allowed here
        return getInstanceImpl();
    }
    public static getInstanceImpl() {
        return new MyImplementation(name)
    }
}

Java编译器本可以代替您完成相同的操作,但由于静态方法实现实例方法既不寻常又令人困惑,因此我猜测Java设计者决定不提供这种“魔法技巧”。


+1 表示这并非普适。这种方法不可能实现是因为 Java 的调用语法,而不是理论上的限制。 - biziclop

1

静态方法不能受到多态行为的影响。这样做没有太多意义。想象一下这种情况,假设你想要的是可能的:

public void foo(MyInterface i) {
    i.getInstance("abc");
}

现在我想使用 MyInterface 的实现(类 A)来调用这个方法,但是由于我不能直接传递类本身,所以我需要传递一个对象:

A a = new A();
foo(a);

现在在foo内,调用类A的实例上的getInstancestatic覆盖。所以现在我被迫创建一个对象来调用静态方法。

我的观点是,在大多数多态的使用情况下,您仍然会受到创建对象的限制,因为在您的原始接口中,该方法是一个实例方法。


“那没有太多意义”:实际上,这样做非常有用。问题是为什么它没有被实现:http://stackoverflow.com/questions/20291984/why-is-overriding-of-static-methods-left-out-of-most-oop-languages。请参考此处以了解如何调用这些覆盖。 - Mr_and_Mrs_D

0

因为实现接口使得实现者成为接口的类型。这意味着实例需要具有由类型定义的方法,而不是实例的类。

换句话说,

public void mymethod

public static void mymethod

不是相同的方法声明。它们完全不同。如果mymethod在接口上定义,那么第二个定义根本不能满足实现接口的要求。


0
答案取决于实现接口的含义。当一个类实现一个接口时,这意味着该类的每个实例都将响应接口中的每个方法。当您将方法实现为静态方法时,您可以在没有类实例的情况下调用该方法 - 但这并不满足继承实现的承诺,即该方法将可在类的每个实例上调用。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接