抽象的な問題: クラスのコンパニオン オブジェクトに混合できる特性を作成して、そのオブジェクトにそのクラスのオブジェクトを返すメソッドを提供します。
具体的な問題: 次のように、自分自身をシリアル化および逆シリアル化する方法を知っている、RESTful サービス呼び出しで使用するための一連のクラスを作成しようとしています。
case class Foo
(
var bar : String,
var blip : String
)
extends SerializeToJson
object Foo extends DeserializeFromJson
使用目的は次のようになります。
var f = Foo( "abc","123" )
var json = f.json
var newF = Foo.fromJson( json )
Genson
グローバルオブジェクトを介してアクセスするシリアライゼーション/デシリアライゼーションを行うために使用しています。
object JSON {
val parser = new ScalaGenson( new GensonBuilder() <...> )
}
次に、特性を次のように定義します。
trait SerializeToJson {
def json : String = JSON.parser.toJson(this)
}
trait DeserializeFromJson[T <: DeserializeFromJson[T]] {
def fromJson( json : String ) : T = JSON.parser.fromJson( json )
}
これはコンパイルされます。しかし、これはしません:
object Foo extends DeserializeFromJson[Foo]
次のエラー メッセージが表示されます。
type arguments [Foo] do not conform to trait DeserializeFromJson's
type parameter bounds [T <: DeserializeFromJson[T]]
次のように、単一の特性を作成しようとしました。
trait JsonSerialization[T <: JsonSerialization[T]] {
def json(implicit m: Manifest[JsonSerialization[T]]) : String =
JSON.parser.toJson(this)(m)
def fromJson( json : String ) : T =
JSON.parser.fromJson(json)
}
宣言しただけでは、コンパニオン オブジェクトではなく、 クラスのインスタンスだけがそのメソッドを持っているため、case class Foo (...) extends JsonSerialization[Foo]
呼び出すことができません。Foo.fromJson
Foo
宣言object Foo extend JsonSerialization[Foo]
すると、コンパイルできFoo
、.fromJson
メソッドが作成されます。しかし、実行時に、 への呼び出しは、それがではなく であるとfromJson
考えます。または、次の実行時エラーが示唆しています。T
JsonSerialization
Foo
java.lang.ClassCastException: scala.collection.immutable.HashMap$HashTrieMap cannot be cast to ...JsonSerialization
at ...JsonSerialization$class.fromJson(DataModel.scala:14)
at ...Foo.fromJson(Foo.scala:6)
そして、私は得るので宣言することはできませobject Foo extends Foo
ん
module extending its companion class cannot use default constructor arguments
したがって、コンストラクターパラメーターを追加してみると、コンパイルして実行できますが、逆シリアル化しようとしたときのランタイムタイプが間違っているため、上記のエラーが発生します。
私ができる唯一のことはfromJson
、すべてのコンパニオン オブジェクトで定義することです。しかし、それを特性で定義する方法がなければならず、その特性を混ぜるだけです。右?