2016-12-15 3 views
0

私がやろうとしていることは簡単だと思いますが、検索用語の集まりは適切ではありません。私が望むのは、すべての実装クラスに、既知の型のオブジェクトで呼び出せるコンストラクタがあることを保証する特性です。構文は次のようにする必要があります。特定の引数を取るコンストラクタを要求する方法はありますか?

trait Message { 
    def this(rdr: msgpack.MsgReader): Message 
} 

しかし、コンパイラは、等号が必要であると私に通知します。どのようにこれを行うにはどのようなアイデア?

+2

コンストラクタは、インタフェースの一部にすることはできません。 –

+0

これは残念です。実装にいくつかの署名のメソッドを持つコンパニオンオブジェクトがあることを強制する方法はありますか? – teryret

+0

コレクション階層からヒントを得て、すべてに強制的に 'コンパニオン:ファクトリ'メソッドを持たせることができますが、それを行うにはインスタンスを必要とします。しかし、一般的に、Scalaの型システムでは、コンパニオン型間を移動することはできません(IMOのように、実際には関係していません)。 – HTNW

答えて

1

代わり型クラスのパターンを使用します。

trait Message[T] { 
    def read(reader: msgpack.MsgReader): T 
    // Example of what would be a normal instance method. 
    // thiz is similar to this, except because we're in another object it must be explicitly taken as parameter. 
    // It's in a separate param list for convention and ease of currying 
    def foo(thiz: T)(param1: Int): Boolean 
} 

// "Implementors" don't actually implement it, the behavior exists as its own singleton 
class Foo { ... } 

implicit object FooMessage extends Message[Foo] { 
    // Note that this is not restricted to just constructors. If you want that then you are really out of luck. (And probably doing it wrong.) 
    override def read(reader: msgpack.MsgReader) = ??? 
    override def foo(thiz: Foo)(param1: Int) = thiz.foo(param1) 
} 

// Usage 
// Use an explicit, named implicit param to avoid implicitly 
def readMsg[T: Message](reader: msgpack.MsgReader) = implicitly[Message[T]].read(reader) 

val foo = readMsg[Foo](???) 
+0

これはきちんとしていますが、私のアプリケーションでは、あなたの他の提案がより好きです(メッセージを工場に送ることができるようにする)。これは受信したメッセージです。つまり、送信側で作業するインスタンスがあるため、送信者はメッセージに工場の名前を尋ねて最初に送信し、受信側はその名前を使用してそのバイトを解析するために使用します。私はそれが好きです、ありがとう! – teryret

関連する問題