简体   繁体   中英

Why does Java permit interfaces to have static readonly fields while .NET interfaces cannot?

I faced with a sample code in Java and it brought me a question.

Java sample code is:

...
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");
}

But in C# we cannot write like that:

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

What is the difference between these two languages/frameworks?

What design policy permit java to have const fields in an interface or what prevents .NET from having that?

The use of interfaces to hold constants is usually frowned on these days in Java too. (I'd say that storing non-compile-time-constant fields like your example is even more frowned upon.)

Fundamentally, it's at odd with the idea of an interface: a contract that the implementation will uphold. The implementation isn't going to provide the field, so what's it doing there?

I suspect the C# team decided that it was sufficiently at odds with the concept behind interfaces to not include it in the language. I don't know whether it's just a C# restriction or a CLR restriction too. For example, I know that the CLR allows interfaces to declare nested types, but C# doesn't currently allow this.

In C#:

Interfaces consist of methods, properties, events, indexers, or any combination of those four member types. An interface cannot contain constants, fields, operators, instance constructors, destructors, or types. It cannot contain static members. Interfaces members are automatically public, and they cannot include any access modifiers.

In Java:

Every field declaration in the body of an interface is implicitly public, static, and final.

Every field in the body of an interface must have an initialization expression, which need not be a constant expression. The variable initializer is evaluated and the assignment performed exactly once, when the interface is initialized.

In Java, all fields in an interface are implicitly static and final. But its considered bad practice. To qoute Joshua Bloch from Effective Java:

The constant interface pattern is a poor use of interfaces. That a class uses some constants internally is an implementation detail. Implementing a constant interface causes this implementation detail to leak into the class's exported API. It is of no consequence to the users of a class that the class implements a constant interface. In fact, it may even confuse them. Worse, it represents a commitment: if in a future release the class is modified so that it no longer needs to use the constants, it still must implement the interface to ensure binary compatibility. If a nonfinal class implements a constant interface, all of its subclasses will have their namespaces polluted by the constants in the interface.

As to why it is considered bad practice, I think a class implementing an interface with constant fields is exposing these in the interface to outside code which consumes this class which in most cases is not what is required.

I think it's weird that Java chose to allow this.

An interface is a contract for a Role. That is, it's an spec that all objects must implement in order to be considered as suitable/swappable candidates for that Role. It should contain the messages/methods that the Role responds to and the notifications that it triggers for interested listeners .

Fields are an implementation detail (and your example contains actual implementation dictating the return value for the INSTANCE field too) and do not belong within the contract. If you wanted to map this to C#, you should probably move it to an abstract base class , which allows default implementation to be specified in addition to specifying some members that derived classes must also implement.

I guess COM's Microsoft Interface Description Language does not allow it. So it's just an adaptation for the Windows environment, much like prefixing interface names with I .

Like most questions of this form, the question is basically pointless. It's not like the designers of Java and C# had a meeting about it. Historically Java came first so you would really have to ask the designers of C#, not that the question would necessarily make sense to them either. It's just how they saw it at the time.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM