如何使用 Scala 的单例对象类型?
我正在编写一个类,作为一系列单例对象的基类。在每个单例对象中,都会有代表某些属性的值,我想编写一个方法,对于每个单例对象,只接受由它创建的对象。
所以我有以下几点:
class Obj[M <: Maker]
class Maker {
implicit val me: this.type = this
def make[M <: Maker](implicit maker: M) = new Obj[M]
def accept(obj: Obj[this.type]) = {...}
}
到目前为止,一切都很好。然后我想声明这些单例对象之一:
object M extends Maker {
val a = make
}
但是,如果我尝试这样做:
M.accept(M.a)
那么我会收到编译时错误:
type mismatch; found : com.test.Obj[object com.test.M] required: com.test.Obj[com.test.M.type]
我的问题:
object com.test.M
的类型是什么,以及如何它与com.test.M.type
不同吗?- 我怎样才能以更聪明的方式做到这一点?
I'm writing a class which serves as base class for a series of singleton objects. In each singleton objects, there will be vals representing certain properties, and I want to write a method which, for each singleton object, only accepts objects created by it.
So I have the following:
class Obj[M <: Maker]
class Maker {
implicit val me: this.type = this
def make[M <: Maker](implicit maker: M) = new Obj[M]
def accept(obj: Obj[this.type]) = {...}
}
So far, so good. Then I want to declare one of these singleton objects:
object M extends Maker {
val a = make
}
But then, if I try this:
M.accept(M.a)
then I get a compile-time error:
type mismatch; found : com.test.Obj[object com.test.M] required: com.test.Obj[com.test.M.type]
My questions:
- What's the type
object com.test.M
, and how is it different fromcom.test.M.type
? - How can I do this in a smarter way?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
与时俱进吧,我的好人!我在 24 小时前就解决了这个问题。接下来,我预计会看到迅猛龙追逐渡渡鸟,一边猛烈地挥动马鞭,一边在点播屏幕保护程序上查找股票报价。
有问题的提交是: http://lampsvn.epfl.ch/trac/scala/changeset /23622
Get with the times, my good man! I fixed this over 24 hours ago. Next I expect to see velociraptors chasing dodos, furiously cracking their buggy whips while looking up stock quotes on their pointcast screensavers.
The commit in question is: http://lampsvn.epfl.ch/trac/scala/changeset/23622
使用
this.type
而不是M
。这个简化的例子应该可以工作:Use
this.type
instead ofM
. This simplified example should work:您的第一个问题,“
object com.test.M
的类型是什么,它与com.test.M.type
有什么不同?”,仍然没有被解决。回答道。我没有在规范中找到它的记录,但似乎object M
类型是表示定义对象M
时隐式创建的类的内部类型。当然,M
是该类的唯一实例,因此人们会期望object M
类型等同于M.type
,但是编译器显然不这么认为。您遇到的问题,如 @retronym 解释的 的问题是,当您调用
make
方法时,不会为类型参数推断单例类型M.type
。这与在下面的会话中推断String
而不是v.type
的原因相同:其中
identity
定义为Your first question, "What's the type
object com.test.M
, and how is it different fromcom.test.M.type
?", still hasn't been answered. I haven't found it documented in the spec, but it seems that theobject M
type is the internal type representing the class that is implicitly created when you define an objectM
. Of course,M
is the only instance of that class so one would expect theobject M
type to be equivalent toM.type
, but the compiler apparently does not see it that way.The problem you're running into, as @retronym explained, is that the singleton type
M.type
is not inferred for the type parameter when you invoke yourmake
method. This is for the same reason thatString
is inferred rather thanv.type
in the session below:where
identity
is defined as这是有效的:
秘密“酱汁”是在单例对象中使用
make[M.type]
。@retronym 值得赞扬解释这一点: 如何正确输入-注释这个 HList?
This works:
The secret "sauce" is using
make[M.type]
inside the singleton object.@retronym deserves the credit for explaining this: How to correctly type-annotate this HList?