【问题标题】:Why can't implementing classes define an overriding method as static?为什么实现类不能将覆盖方法定义为静态?
【发布时间】:2012-07-03 01:07:29
【问题描述】:

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

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) 方法,但我目前仅限于在对象已经被实例化的情况下才能调用该方法,哪种方式违背了目的......


*update:* 感谢您的回答,我现在明白了。基本上我不应该试图让一个实用程序类(或工厂类)实现一个接口(或者至少不是以这种方式)......

【问题讨论】:

  • 想一想,如何调用被覆盖的静态方法?
  • @TedHopp 从技术上讲,这与那个问题完全相反。
  • 这不是关于 interface 方法是静态的,而是允许我将 implementing 方法设为静态。所以我可以打电话给MyImplementation.getInstance("foo"); 而不是new MyInterface("foo").getInstance("foo");
  • 请注意,在您的示例中,静态覆盖的签名与接口方法的签名不匹配。这甚至不是一个有效的覆盖。

标签: java inheritance interface static static-methods


【解决方案1】:

在 Java 中调用静态方法需要您指定确切的类型。不能多态地调用静态方法,因此不需要@Override

请注意,这种方法并非在所有语言中都通用:例如,您可以在 Objective-C 中重写 类方法,Apple 的 cocoa 框架很好地利用了这种机制来定制他们的“工厂” “课。但是,在 Java、C++ 和 C# 中,类方法不支持多态行为。

理论上,Java 设计人员可以让您通过static 方法提供接口方法实现,以防实现不需要从实例访问状态。但是使用简单的包装器很容易实现相同的行为:

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 调用语法使这种方法变得不可能,而不是理论上的界限。
【解决方案2】:

静态方法不能受到多态行为的影响。那没有多大意义。想象一下这个用例,假设你想要什么是可能的:

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

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

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

现在在foo 内部,getInstancestatic 覆盖在A 类的实例上被调用。所以现在我坚持创建一个对象只是为了调用一个静态方法。

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

【讨论】:

  • “那没有多大意义”:它会——而且它也会非常有用。问题是为什么它没有被实施:stackoverflow.com/questions/20291984/…。请参阅此内容,了解如何调用这些覆盖
【解决方案3】:

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

换句话说,

public void mymethod

public static void mymethod

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

【讨论】:

    【解决方案4】:

    答案归结为实现接口意味着什么。当一个类实现一个接口时,这是一个承诺,即该类的每个实例都将响应接口中的每个方法。当您将方法实现为静态时,您可以在没有类实例的情况下调用方法 - 但这并不能满足继承实现的承诺,即该方法可以在每个实例上调用班级。

    【讨论】:

      猜你喜欢
      • 2017-10-06
      • 2011-09-16
      • 2011-04-26
      • 1970-01-01
      • 1970-01-01
      • 2014-09-28
      • 1970-01-01
      • 2013-12-15
      • 1970-01-01
      相关资源
      最近更新 更多