2016-12-15 79 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

相关问题