web-dev-qa-db-ja.com

Scalaトレイトを使用したクライアント構成と抽象クラスの実装

Scalaでは、基本クラスを拡張するために、抽象クラスの代わりにトレイトを使用することをお勧めします。

次のデザインパターンとレイアウトは適切ですか?これは、TraitsがAbstractを置き換えることを意図した方法ですか?

  • クライアントクラス(def function1を使用)
  • trait1クラス(function1をオーバーライドします)
  • trait2クラス(function1をオーバーライドします)
  • specificClient1はtrait1でクライアントを拡張します
  • specificClient2はtrait2でクライアントを拡張します
34
kliew

Scalaの抽象クラスよりも特性を優先すべきであるという主張の出典はわかりませんが、いくつかの理由がありますnot

  1. 特性はJavaの互換性を複雑にします。コンパニオンオブジェクトを持つトレイトがある場合、Javaからコンパニオンオブジェクトのメソッドを呼び出すには、奇妙なMyType$.MODULE$.myMethod構文が必要です。これは、静的メソッドとインスタンスメソッドを持つ単一のクラスとしてJVMに実装されるコンパニオンオブジェクトを持つ抽象クラスには当てはまりません。 Scalaで具体的なメソッドを使用してJavaトレイトを実装することは、さらに不快です。
  2. 実装を含むメソッドをトレイトに追加する バイナリ互換性を破る 具体的なメソッドをクラスに追加しない方法で。
  3. 特性により、フォワーダーメソッドの使用に関連するバイトコードとオーバーヘッドが増加します。
  4. 特性はより強力ですが、これは悪いことです。一般に、仕事を遂行するために最も強力でない抽象化を使用する必要があります。彼らがサポートする種類の多重継承が必要ない場合(そして非常に多くの場合、必要ない場合)、それにアクセスできない方が良いでしょう。

最後の理由は、私の見解では断然最も重要です。少なくとも他のいくつかの問題 修正される可能性があります Scalaの将来のバージョンでは、クラスをデフォルトにすると、(少なくともほぼ間違いなく)良好と一致する方法でプログラムが制約される場合があります。設計。あなたが実際に特性によって提供される力を本当に望んでいるとあなたが決めるならば、それらはまだそこにあります、しかしそれはあなたがする決定であり、あなたがただ滑り込むものではありません。

したがって、他の情報がない場合は、抽象クラス(理想的には封印されたクラス)と実装を提供する2つの具象クラスを使用することをお勧めします。

67
Travis Brown

OTOHの特性を使用すると、複雑なオブジェクトの機能をきめ細かく構築およびテストし、コアロジックを再利用してさまざまなフレーバーを提供できます。たとえば、ドメインオブジェクトをデータベースに永続化するデータサーバーにデプロイし、Webサーバーがデータサーバーから更新された同じオブジェクトの読み取り専用バージョンを使用する場合があります。

すべてのシナリオに適したものはありません。手元のタスクに適切な構成を使用してください。実装の現実が、設計時には未知であった特定のユースケースの問題を明らかにする場合があります。さまざまな仮定と構成を使用して再実装すると、驚くべき結果が得られる可能性があります。

3
Mike Slinn