web-dev-qa-db-ja.com

委任が必要な場合のscalaケースクラスの使用方法

このアプリケーションで、車をモデル化するとします。また、登録済みの車を保管する車のリポジトリをモデル化する必要があります。それをscalaでどのようにモデル化する必要がありますか?

これが私のアプローチです。まず、ケースクラスPlainCarを作成します。これは、現実の世界に存在する車であり、特別なことは何もありません。次に、CarRepositoryを作成します。 RegisteredCarも作成します。 CarRepositoryPlainCarsを保存し、それらをRegisteredCarsとして返すことができるようになりました。 PlainCarRegisteredCarはどちらも、Carのようなすべてのcomonメソッドを提供する特性driveを拡張します。ただし、RegisteredCarは特別です。PlainCarのインスタンスを所有しますが、登録番号を返すメソッドregistrationNumberも追加します。他のすべてのメソッドは、PlainCarインスタンスに委任されるだけです。

しかし、このデザインにはいくつかの欠陥があるように感じます。 1つは、メソッド/プロパティをRegisteredCarに追加するときに、PlainCarを変更する必要があることです。これは、実行する必要はないと思います。

したがって、私の質問は、これをより適切にモデル化できるか、もしそうなら、どのようにモデル化できるかということです。私が見逃している他の欠点はありますか?

PlainCarは私にはかなり厄介に聞こえるので、命名規則に関するいくつかのアドバイスもいただければ幸いです。

3
valenterry

登録は、リポジトリのコンテキストでのみ意味を持つ状態であるかのように聞こえます。 2つの状態について説明しました(リポジトリに登録されている、リポジトリに登録されていない)。必要なのは車のコンテナ(お望みならラッパー)のように聞こえます。 Option [Car]または[Car、Motorbike]が1つのオブジェクトしか保持できないのと同じように、1台の車を保持できるコレクションと考えてください。

したがって、RepositoryItem封印された基本特性(または封印された抽象クラス)を作成し、各状態のケースクラスインスタンス(RepositoryItemを拡張する)を作成します。登録済みバリアントには登録番号があります。 RepositoryRepositoryItemsのコンテナを作成します。同じケースクラスのセットの一部であってはなりません。

このアプローチの利点は次のとおりです。

  • RepositoryItem [Car]ではなく、汎用(RepositoryItem [A]またはRepositoryItem [+ A])にすることができます。これは、他のもののリポジトリになる可能性があることを意味します(または、バイクや車を保持するために簡単に拡張できます)。
  • リポジトリの実装と自動車の実装の間の関心の分離。一方は、他方に影響を与えることなく変更(または新しい機能を追加)できます。
  • Carの新しいサブクラスは何度でも作成できます。 Repository [Car]を最初から作成しても、汎用にするのではなく、変更なしでCarサブクラスを保持できます。

オプションどちらかの設計方法をご覧ください。少なくともmapを実装して、リポジトリスロットから車を取り出さなくても、車を操作(または自転車に置き換える)できるようにすることをお勧めします。

編集:

あなたのコメントから判断して、混乱を引き起こしたかもしれない点を説明するために...

OptionおよびEitherタイプには、map関数があります(Listおよびその他のモナドと同様)。 map関数を使用すると、含まれているオブジェクトを操作できる関数を渡すことができます。 Optionにラップされたままの変換されたオブジェクトが返されます。

scala> val o = Some(3)
o: Some[Int] = Some(3)

scala> o map (_ * 5)
res2: Option[Int] = Some(15)

OptionIntの間に依存関係はありませんが、Optionmapを実装しているため、Intを操作できます。 =削除せずにオプションラッピング。

3
itsbruce

何かが足りないような気がしますが、あなたのCarRepositoryMap[RegistrationNumber, PlainCar]または同様のもの。通常、不変オブジェクトを使用すると、元のオブジェクトの外部でこの種の関連付けを作成する方がはるかに簡単です。

私の2番目の選択肢はRegisteredCar extends PlainCarですが、これにより不要な結合とコピーが作成されると思います。これらのオプションはどちらも、PlainCarの名前をCarに変更するだけです。

2
Karl Bielefeldt