1つのクラスを拡張するすべての型がJavaコレクションにパックされているプロジェクトで予期しない状況が発生しましたが、そのクラスの特定の拡張のみに追加のメソッドが含まれています。それを " ) ";そして、他の拡張機能がそれを持たないことを明確にしましょう。そのコレクション内のすべてのアイテムに対して1つのタスクを実行する直前に、それを実装するすべてのアイテムに対してalso()を呼び出す必要があります。
最も簡単な方法はこれです:
stuff.stream().filter(item -> item instanceof SpecificItem)
.forEach(item -> ((SpecificItem)item).also()));
stuff.stream().forEach(item -> item.method());
正常に動作しますが、そこにある「instanceof」に慣れていません。これは一般的にコードの悪臭のマーカーです。このクラスを取り除くためだけに、このクラスをリファクタリングする可能性は非常に高いです。しかし、劇的なことをする前に、コミュニティに問い合わせて、StreamsまたはCollectionsのどちらかについてより経験のある人がより簡単な解決策を持っているかどうかを確認したいと思いました。
例(確かに非排他的)として、クラスによってエントリをフィルタリングするコレクションのビューを取得することは可能ですか?
私は.map
呼び出してキャストを行います。その後、後のコードで「本物」を使用できます。
前:
stuff.stream().filter(item -> item instanceof SpecificItem)
.forEach(item -> ((SpecificItem)item).also()));
後:
stuff.stream().filter(item -> item instanceof SpecificItem)
.map(item -> (SpecificItem)item)
.forEach(specificItem -> specificItem.also()));
これは完璧ではありませんが、少し片付けているようです。
1つのクラスを拡張するすべての型がJavaコレクションにパックされているプロジェクトで予期しない状況が発生しましたが、そのクラスの拡張のみがメソッドを実装しています。それを "also()"と呼びましょう。そのコレクション内のすべてのアイテムに対して1つのタスクを実行する直前に、それを実装するすべてのアイテムに対してalso()を呼び出す必要があります。
それは明らかに欠陥のある設計です。あなたが書いたものからは明らかではありません、それが何を意味するのか、あるクラスはimplementメソッドではないということです。それがnothingを単に行う場合、それは問題ではないので、不要な副作用があると思います。
正常に動作しますが、そこにある「instanceof」に慣れていません。
あなたの根性は正しいです。オブジェクト指向の優れたデザインは、オブジェクトが正確に何であるかを知ることなく機能し、特別な種類のインスタンスであるかどうかに関係します。
しかし、劇的なことをする前に、コミュニティに問い合わせて、StreamsまたはCollectionsのどちらかについてより多くの経験がある人がより簡単な解決策を持っているかどうかを確認するつもりだと思いました。
リファクタリングは劇的ではありません。コードの品質が向上します。
与えられたコードベースで最も簡単な解決策は、確実にするために、親と子クラスを持つ2つの別々のコレクションを用意することです。しかし、それはかなりきれいではありません。
SpecificItem
とalso()
が実際に何であるかを知らずに特定の推奨事項を提供することは困難ですが、
SpecificItem
のスーパークラスでalso()
を定義します。何もしないデフォルトの実装を指定します(空のメソッド本体を指定してください)。必要に応じて、個々のサブクラスでオーバーライドできます。 also
が実際に何であるかによって、関係するすべてのクラスにとって意味のある名前に変更する必要がある場合があります。
ここにも明らかなものが欠けていないことを願っています(これも @ Tristan Burnsideのコメント で示唆されています)が、なぜSpecificItem.method()
が最初にalso()
を呼び出せないのですか?
public class SpecificItem extends Item {
...
public void method() {
also();
super.method();
}
}
例(確かに非排他的)として、クラスによってエントリをフィルタリングするコレクションのビューを取得することは可能ですか?
おそらくパフォーマンスへの影響(YMMV)を犠牲にして、クラスのキーとしてcollect()
をCollectors.groupingBy()
にして、結果として得られたMap
から必要なものを選択するという、ストリームyの方法を考えることができます。値はList
として格納されるため、Set
に対してこのようなフィルタリングを行うことを期待していて、フィルタリングされたSet
を取得したい場合は、結果のSet
にも値を追加するための追加の手順が必要になります。
代替:
そうすれば、インターフェイスを実装するオブジェクトだけがテーマ自体をメソッドに渡すことができます... instanceofを使用する必要はありません
public class MyStream extends Stream
{
//...
Stream<Filterable> filter(Predicate<? implements Filterable> predicate)
{
return super.filter(predicate);
}
}