2016-02-07 6 views
33

私はScalaでこれを読んでいますが、一般に、抽象クラスの代わりにTraitsを使用して基底クラスを拡張することをお勧めします。Traitを使ったScalaクライアントの作成と抽象クラスの実装との比較

次のデザインパターンとレイアウトは良いですか? TraitsがAbstractを置き換えることを意図したのはこれですか? (DEF機能1を有する)

  • クライアントクラス
  • trait1クラス(機能1を上書き)
  • trait2クラス(機能1を上書き)
  • specificClient1はtrait1
  • specificClient2がtrait2
とクライアントを拡張して、クライアントを拡張します

答えて

66

私は、あなたがScalaの抽象クラスよりも特性を優先させるべきであるという主張が何であるか分かりませんが、再ないにいくつかの理由されています

  1. 形質はJavaの互換性を複雑にします。コンパニオンオブジェクトを持つ特性を持つ場合、Javaからコンパニオンオブジェクトのメソッドを呼び出すには、奇妙な構文MyType$.MODULE$.myMethodが必要です。コンパニオンオブジェクトを持つ抽象クラスは、静的メソッドとインスタンスメソッドを持つ単一クラスとしてJVMに実装されています。 Javaで具体的なメソッドを使用してScalaの特性を実装することは、さらに不愉快です。
  2. 具体的なメソッドをクラスに追加する方法では、形質を実装したメソッドをbreaks binary compatibilityに追加することはできません。
  3. Traitを使用すると、バイトコードが多くなり、転送メソッドの使用に関連するオーバーヘッドが増加します。
  4. 形質がより強力です。これは悪いことですが、一般に、ジョブを実行する最も強力な抽象化を使用したいと考えています。彼らがサポートしている多種の継承を必要としない場合(非常に頻繁にはそうしない場合)、アクセスしないほうがよいでしょう。

最後の理由は、私の見解では最も重要です。 Scalaの将来のバージョンでは少なくともの2つの問題が残っていますが、クラスにデフォルトを設定することは、(少なくとも間違いなく)良い設計と一貫性のある方法でプログラムを制約するケースにとどまります。あなたが本当に本当に本当に特性によって提供される力をしたいと思うなら、彼らはまだそこにいるでしょうが、それはあなたがしているものではなく、あなたが決定するでしょう。

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

+2

脚注として、スカラの線形化のアプローチは、複数の継承の「問題」に対する巧妙な解決策です。必要なときには、フィールドのようないくつかの例外を除いて、かなりうまく機能します。しかし、賢いというだけで何かを使うべきではありません。 –

+1

ありがとう、それは私の質問に答える。私のソースはhttps://www.safaribooksonline.com/library/view/scala-cookbook/9781449340292/ch04s13.htmlでした。 – kliew

+1

Scala [2.12](http://www.scala-lang.org/news/2.12.0)で#1-3は、 "特性が直接にコンパイルされます。これはバイナリ互換性とJava相互運用性を向上させます。もちろん、#4は「特性」よりも「抽象クラス」を選択するのに十分な理由だと私は信じている。 @ TravisBrown –

2

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

すべてのシナリオに適切なものはありません。手元のタスクに適切な構成を使用してください。実装の現実は、設計時に不明だった特定のユースケースに対して軽い問題を引き起こすことがあります。異なる前提条件と構造を使用して再実装すると、驚くべき結果が得られます。

関連する問題