3

次のcaseクラスをシリアル化する場合、val要素は含まれません。それはなぜですか、それを含めることはできますか?

case class Asset(id: Option[Int], description: Option[String]= None) {
  val url = "images/" + id.toString+".png"
}

更新:Jsonライブラリを追加し、URL「property」の仕様/使用目的を追加しました。

Play 2.1 /Scala2.10に同梱されているJsonライブラリを使用しています。

実際には、urlプロパティは、構成に従って変換アルゴリズムを検索する関数であることが意図されています。たとえば、画像はローカルで利用できる場合もあれば、外部ホストから利用できる場合もあります。

4

1 に答える 1

2

使用しているjsonシリアライゼーションライブラリを実際に指定する必要がありますが、次のことを行うだけで機能することがほぼ保証されています。

case class Asset(id: Option[Int], description: Option[String]= None, url = "images/" + id.toString+".png")

とにかくデフォルト値があるとすれば、urlそれをパラメーターに変えてもコードに悪影響を与えることはありません (Asset(None)以前のように、例によって行うことができます)。唯一の欠点は、クライアント コードがAssetに対して異なる値を持つインスタンスを作成するurl可能性があることです。

その場合、おそらくAssetクラス用のカスタム json 形式を作成する必要がありますが、どのシリアル化ライブラリを使用しているかを知らなければ、この点でこれ以上のことはできません。


更新

urlおっと、のデフォルト値が別のパラメータに依存するという事実を完全に見逃していました( id)(気づいてくれた@Kristian Domagalaに感謝します)。したがって、上記のスニペットはコンパイルされません。簡単な解決策の 1 つはurl、@Kristian Domagala が提案するように、2 番目のパラメータ リストを追加することです。

case class Asset(id:Option[Int],description:Option[String]=None)(val url:String = "images/" + id.toString+".png")

Assetしかし、これは(urlインスタンスを比較するときに考慮されなくなった)の等値セマンティクスを変更し、構築構文も変更するため、理想的ではない可能性があります: 値を明示的に指定する場合は、例ではなく次のurlようにする必要があります。. これらの欠点に耐えることができる場合、これは確かに最も簡単な解決策です.Asset(Some(123))("gfx/myImage.png")Asset(Some(123), url="gfx/myImage.png")

Asset.applyそれ以外の場合は、別の回避策があります。 (手動で) 自分自身を再定義できます。

case class AssetImpl( val id: Option[Int], val description: Option[String], val url: Option[String]) {
  override def productPrefix = "Asset"
}
type Asset = AssetImpl
object Asset {
  def apply( id: Option[Int], description: Option[String] = None, url: Option[String] = None ) = {
    new Asset( id, description, url.orElse( id.map( "images/" + _ + ".png") ) )
  }
}

ご覧のとおり、 のデフォルト値を持つ に変わりurlました(以前のコンパイル エラーを回避します。これは、もはや依存しないためです)。の) の.OptionNoneiddef apply...Asseturlidid.map( "images/" + _ + ".png")

残りは基本的に、再定義できるノイズにすぎAsset.applyません。実際には、ケース クラスのファクトリを再定義することはできません (別のオーバーロードを追加することしかできません)。そこで、クラスの名前を に変更しAssetImpl、タイプ エイリアスを追加して、誰も気付かないように ( ;-) )、メソッドAssetを定義する独自のオブジェクトを作成しました (これは、自動生成されたメソッドapplyと競合しなくなりました。apply単純に標準クラス (非ケース クラス) に変更するAssetImplこともできますが、再定義する必要があり、クラスにフィールドを追加/削除するときに維持する必要があることを考えると、より面倒です。AssetequalshashCode

于 2013-02-13T15:47:25.937 に答える