2012-09-05 12 views
8

私はScalaにはかなり新しく、APIライブラリを作成し、valと不変オブジェクト(可能な場合)のみを使用しようとしています。私はオブジェクトをモデル化する正しい方法を決定しようとしています。スカラ拡張パラメータ付き抽象クラス

abstract class Post(val id: Int, val name: String, ...) 
case class TextPost(val id: Int, val name: String, ..., val text: String) extends Post(id, name, ...) 
case class PhotoPost(val id: Int, val name: String, ..., val url: String) extends Post(id, name, ...) 

この方法は、多くを扱う場合は特に、繰り返しの宣言とボイラープレートコードの多くを追加しますが、いくつかの「ポスト」のオブジェクトがどのすべての共有いくつかの共通のフィールド、しており、それぞれが独自の特定のフィールドを追加したとポストサブクラスと共有フィールドは、抽象クラスで宣言します。私はそれを見る方法で、これはコンストラクタによってのみ初期化できるvalの使用によって引き起こされます。ここで説明した関係を作成するためのより良い方法がありますか、または不変のオブジェクトだけを使用したい場合にはこれを苦労しなければなりませんか?

答えて

8

まず、case-classコンストラクタのval修飾子が冗長であるため、Scalaコンパイラはすでに "無料"(これはcase-classesの機能の1つ)です。あなたが実際にそれをコンパイルしようとした場合は、エラーが原因で宣言されていない最優先のために発生していることがわかります。

abstract class Post(val id: Int, val name: String) 
case class TextPost(id: Int, name: String) extends Post(id, name) 
case class PhotoPost(id: Int, name: String) extends Post(id, name) 

<console>:10: error: overriding value id in class Post of type Int; 
value id needs `override' modifier 
      case class PhotoPost(id: Int, name: String) extends Post(id, name) 
           ^

私は個人的にはできるだけコンストラクタ引数を持つ抽象クラスを使用することをお勧めします。 Scalaはここでより良い仕事をする特性を持っています。コンストラクタの引数の代わりに、フィールドを(抽象的に)宣言します。その後、ケースクラスが原因それらが自動的にvalsをその引数を作ることにしてキックして、あなたが行われています。

trait Post { def id: Int; def name: String } 
case class TextPost(id: Int, name: String, text: String) extends Post 
case class PhotoPost(id: Int, name: String, url: String) extends Post 

さらに、あなたはtrait Postsealedを追加した場合、あなたが安全に誤っせずにパターンマッチングでPostのサブタイプを使用することができます不足しているケース。

+0

ありがとうございます!ボイラー・プレート・コードに関して、このメソッドは基本的に、派生クラスの各パラメーターをvalとして宣言するのを防ぎますが、各宣言ですべてのパラメーターを繰り返す必要があります。私は8つのサブクラスと15の共有フィールドを持っているので、これを強調しています。これは、このような巨大なDRYケースのようです。しかし、私はあなたの答えから、これを回避する方法はない、と理解していますよね? – orrsella

+1

これ以外の唯一の方法は、共通インタフェース( 'Post')を実装することではありません。つまり、型を含める必要があることを意味しますが、それがあなたの望むものなのかどうかはわかりません: 'case class Post(id:Int、name:String);大文字小文字のクラスTextPost(投稿:投稿、テキスト:文字列) '。 –

+5

ボイラープレートの質問に答えることができないので、この答えは十分ではないと思います... –