2016-12-15 82 views
0

我認爲我想要做的事很容易,但我沒有得到正確的搜索關鍵詞。我想要的是保證所有實現類都具有可以用已知類型的對象調用的構造函數的特徵。語法應該是:有沒有辦法要求具有特定參數的構造函數?

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

但編譯器告訴我它期望等號。任何想法如何做到這一點?

+2

構造不能是接口的一部分。 –

+0

這很不幸。有沒有辦法強制實現有一個伴侶對象有一些簽名的方法? – teryret

+0

您可以從收集層次結構中獲取提示,並強制所有內容都有「伴侶:工廠」方法,但這需要您有一個實例,然後才能製作更多內容。你也可以使用類型類,這可以解除這個限制。但是,一般來說,Scala的類型系統不允許你在同伴類型之間移動(並且有很好的理由,因爲它們並不真正相關)。 – 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

相關問題