为什么Java允许接口具有静态只读字段而.NET接口不能?

时间:2010-08-01 06:43:41

标签: java .net language-design

我面对Java中的示例代码,它给我带来了一个问题。

Java 示例代码为:

...
public interface CLibrary extends Library {
    CLibrary INSTANCE = (CLibrary) Native.loadLibrary((Platform.isWindows() ? "msvcrt" : "c"), CLibrary.class);
    void printf(String format, Object... args);
}

public static void main(String[] args) throws IOException {
    CLibrary.INSTANCE.printf("Hello, World\n");
}

但是在 C#中,我们不能这样写:

public interface IMyInterface {
    static readonly int staticInt = 5;                          // compile error
    static readonly SomeClass staticInstance = new SomeClass(); // compile error
}

这两种语言/框架之间有什么区别?

什么样的设计策略允许java在接口中使用const字段或什么阻止.NET拥有它?

6 个答案:

答案 0 :(得分:6)

在Java中,使用接口来保存常量通常也不受欢迎。 (我会说存储非编译时常量字段就像你的例子更令人不悦。)

从根本上说,接口的概念很奇怪:实现将支持的合同。实现不会提供该字段,那么它在那里做什么?

我怀疑C#团队认为它与界面背后的概念完全不符,而不是在语言中包含它。我不知道它是仅仅是C#限制还是CLR限制。例如,我知道CLR允许接口声明嵌套类型,但C#目前不允许这样做。

答案 1 :(得分:2)

In C#:

  

接口由方法组成,   属性,事件,索引器或任何   这四个成员的组合   类型。界面不能包含   常量,字段,运算符,实例   构造函数,析构函数或类型。   它不能包含静态成员。   接口成员是自动的   公众,他们不能包括任何   访问修饰符。

In Java:

  

正文中的每个字段声明   界面是隐式公开的,   静态的,最后的。

     

身体中的每个领域   接口必须有初始化   表达,不一定是   不断表达。变量   初始化程序被评估和   任务完成一次,   界面初始化时。

答案 2 :(得分:0)

在Java中,接口中的所有字段都是隐式静态和最终字段。 但它被认为是不好的做法。来自Effective Java的Joshua Bloch:

  

常量接口模式是a   接口使用不当。那一堂课   内部使用一些常量是一个   实施细节。实施一个   常量接口导致此   实施细节泄漏到   class的导出API。没有   对班级用户的影响   该类实现了一个常量   接口。事实上,它甚至可能   混淆他们。更糟糕的是,它代表了一个   承诺:如果在将来发布   类被修改,以便它不再   需要使用常量,它仍然   必须实现接口以确保   二进制兼容性如果是非最终的   class实现一个常量接口,   它的所有子类都有它们的   被常量污染的名称空间   在界面中。

至于为什么它被认为是不好的做法,我认为实现具有常量字段的接口的类在接口中暴露这些消耗这个类的外部代码,在大多数情况下这不是所需的。

答案 3 :(得分:0)

我认为Java选择允许这一点很奇怪。

接口是角色的合同。也就是说,它是一个规范,所有对象必须实现,以便被视为该角色的合适/可交换候选者。它应该包含角色响应的消息/方法以及它为感兴趣的侦听器触发的通知

字段是一个实现细节(您的示例包含指示INSTANCE字段的返回值的实际实现),并且不属于合同。如果要将其映射到C#,则应该将其移动到抽象基类,除了指定派生类还必须实现的某些成员之外,还允许指定默认实现。

答案 4 :(得分:0)

我猜COM的Microsoft接口描述语言不允许它。所以它只是适用于Windows环境,就像在I前缀接口名称一样。

答案 5 :(得分:0)

与此形式的大多数问题一样,这个问题基本上没有意义。这并不像Java和C#的设计师就此开会。历史上Java首先出现,所以你真的要问C#的设计者,而不是问题对他们来说也是必要的。这就是他们当时的看法。