让我们假设以下 Java 场景
public interface Foo {
Object bar();
}
public class Baz implements Foo {
public Object bar() {
//My implementation
}
}
为什么我不能将
Baz.bar()
设为静态?
这样做会导致编译器错误
This static method cannot hide the instance method from Foo
向 @Override
添加 Baz.bar()
注释会将编译器错误更改为 The method bar() of type Baz must override or implement a supertype method
在我看来,从使用接口
Foo
的任何人的角度来看,实现类Baz
仍然可以满足接口要求,同时为任何显式使用Baz
的人提供一个具有静态实现的方法。
没有实例化的类。
为什么编译器不允许这种情况呢?
编辑:
也许我不够清楚,但我实际上要问的是为什么这是不允许的,因为从我的角度来看,我并没有降低接口定义方法的可见性。
是的,我知道我在标题中使用了“摘要”一词,而不是在问题中,但那是因为
abstract
关键字隐含在界面中。
编辑2:
我将添加一个更接近现实的例子,以清楚地说明我为什么要问这个:
public interface DatabaseMapper<T extends DatabaseType> {
Entry<T> convert(Entry);
}
public interface SQL extends DatabaseType {}
public class SQLEntry implements Entry<SQL> {}
public class SQLMapper implements DatabaseMapper<SQL> {
public SQLEntry convert(Entry e) {
//Convert some generic entry to the SQLEntry type
}
}
在这种情况下,我想强制所有
Mapper
实现实现 convert
方法,但同时,此方法可能不以任何方式依赖于 SQLMapper
对象的内部状态,并且它可能希望能够将通用 Entry
转换为 SQLEntry
,而无需经历可能包括数据库连接字符串等的实例化过程。
这就是我面临的情况,以及为什么我想看看是否有人知道为什么用相同的方法无法完成这件事 - 例如不必求助于被重写方法将其实现委托给的
public static SQLEntry convertStatic(Entry e)
。
不过,我再次明白,由于编译器的工作方式,这在 Java 中是不可能的 - 我只是想理解为什么会这样。
真正的答案是 Java 根本就不是这样定义的。在其他语言中,这是可能的。
例如,在 Scala 中没有静态方法,但您可以定义 static
object
,它们是单例的并且允许这样做。在像 Smalltalk 或 Ruby 这样的动态语言中,类就像对象,这也是可能的。
但是在Java中,静态方法与全局方法类似。静态方法中没有
self
和 super
的概念,因为它没有绑定到对象。因此,继承/重写并不真正适用。
这表明,如果没有继承的概念,那么谈论
abstract
就没有意义。
public class Baz implements Foo {
public Object bar() {
//My implementation
}
public static Object bar() {
//My implementation
}
}
因为,你们的方法签名是相同的,所以 bar() 没有重载。由于您在抽象类中声明了一个非静态 bar() ,因此您被迫在此类中实现该方法。
抽象方法应该由子类方法覆盖(定义)。您无法重写静态方法,因为它们不属于实例,而是属于它们定义的特定类。
例如,使用非静态方法:
Foo b = new Baz();
Object result = b.bar();
static 的用法如下:
Object result = Baz.bar2();
如果您确实希望 bar 是静态的并且还希望在实例级别进行覆盖,请执行以下操作:
public interface Foo {
Object bar();
}
public class Baz implements Foo {
@Override
public Object bar() {
return Baz.bar2();
}
public static Object bar2() {
//your implementation
}
}