Javaインターフェースのオプションメソッド 質問する

Javaインターフェースのオプションメソッド 質問する

私の理解では、Java でインターフェースを実装する場合、そのインターフェースで指定されたメソッドは、そのインターフェースを実装するサブクラスによって使用される必要があります。

Collection インターフェイスなどの一部のインターフェイスには、オプションとしてコメントされているメソッドがあることに気づきましたが、これは正確にはどういう意味ですか? インターフェイスで指定されているすべてのメソッドが必須であると思っていたので、少し戸惑いました。

ベストアンサー1

ここでの回答には非常に多くの混乱があるようです。

Java 言語では、インターフェース内のすべてのメソッドがそのインターフェースのすべての実装によって実装される必要があります。以上です。このルールには例外はありません。「コレクションは例外です」と言うことは、ここで実際に何が起こっているかについての理解が非常に曖昧であることを示唆しています。

インターフェースへの準拠には 2 つのレベルがあることを認識することが重要です。

  1. Java言語でチェックできるもの。これは要するに、いくつかの各メソッドの実装は?

  2. 実際に契約を履行します。つまり、実装はインターフェースのドキュメントに記載されているとおりに動作しますか?

    よく書かれたインターフェースには、実装から何が期待されるかを正確に説明するドキュメントが含まれています。コンパイラはこれをチェックできません。ドキュメントを読んで、そこに書かれていることを実行する必要があります。契約に書かれていることを実行しないと、インターフェースの実装はコンパイラ is concerned, but it will be a defective/invalid implementation.

When designing the Collections API Joshua Bloch decided that instead of having very fine-grained interfaces to distinguish between different variants of collections (eg: readable, writable, random-access, etc.) he'd only have very coarse set of interfaces, primarily Collection, List, Set and Map, and then document certain operations as "optional". This was to avoid the combinatorial explosion that would result from fine-grained interfaces. From the Java Collections API Design FAQ:

To illustrate the problem in gory detail, suppose you want to add the notion of modifiability to the Hierarchy. You need four new interfaces: ModifiableCollection, ModifiableSet, ModifiableList, and ModifiableMap. What was previously a simple hierarchy is now a messy heterarchy. Also, you need a new Iterator interface for use with unmodifiable Collections, that does not contain the remove operation. Now can you do away with UnsupportedOperationException? Unfortunately not.

Consider arrays. They implement most of the List operations, but not remove and add. They are "fixed-size" Lists. If you want to capture this notion in the hierarchy, you have to add two new interfaces: VariableSizeList and VariableSizeMap. You don't have to add VariableSizeCollection and VariableSizeSet, because they'd be identical to ModifiableCollection and ModifiableSet, but you might choose to add them anyway for consistency's sake. Also, you need a new variety of ListIterator that doesn't support the add and remove operations, to go along with unmodifiable List. Now we're up to ten or twelve interfaces, plus two new Iterator interfaces, instead of our original four. Are we done? No.

Consider logs (such as error logs, audit logs and journals for recoverable data objects). They are natural append-only sequences, that support all of the List operations except for remove and set (replace). They require a new core interface, and a new iterator.

And what about immutable Collections, as opposed to unmodifiable ones? (i.e., Collections that cannot be changed by the client AND will never change for any other reason). Many argue that this is the most important distinction of all, because it allows multiple threads to access a collection concurrently without the need for synchronization. Adding this support to the type hierarchy requires four more interfaces.

Now we're up to twenty or so interfaces and five iterators, and it's almost certain that there are still collections arising in practice that don't fit cleanly into any of the interfaces. For example, the collection-views returned by Map are natural delete-only collections. Also, there are collections that will reject certain elements on the basis of their value, so we still haven't done away with runtime exceptions.

When all was said and done, we felt that it was a sound engineering compromise to sidestep the whole issue by providing a very small set of core interfaces that can throw a runtime exception.

When methods in the Collections API are documented as being "optional operations", it does not mean that you can just leave the method implementation out in the implementation, nor does it mean you can use an empty method body (for one thing, many of them need to return a result). Rather, it means that a valid implementation choice (one that still conforms to the contract) is to throw an UnsupportedOperationException.

Note that because UnsupportedOperationException is a RuntimeException you can throw it from any method implementation, as far as the compiler is concerned. For example, you could throw it from an implementation of Collection.size(). However, such an implementation would violate the contract as the documentation for Collection.size() does not say that this is permitted.

Aside: The approach used by Java's Collections API is somewhat controversial (probably less now than when it was first introduced, however). In a perfect world, interfaces would not have optional operations, and fine grained interfaces would instead be used. The problem is that Java supports neither inferred structural types or intersection types, which is why attempting to do things the "right way" ends up becoming extremely unwieldy in the case of collections.

おすすめ記事