如何使用 Scala 的单例对象类型?

发布于 2024-10-04 19:48:43 字数 749 浏览 3 评论 0原文

我正在编写一个类,作为一系列单例对象的基类。在每个单例对象中,都会有代表某些属性的值,我想编写一个方法,对于每个单例对象,只接受由它创建的对象。

所以我有以下几点:

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]

我的问题:

  1. object com.test.M 的类型是什么,以及如何它与com.test.M.type不同吗?
  2. 我怎样才能以更聪明的方式做到这一点?

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:

  1. What's the type object com.test.M, and how is it different from com.test.M.type?
  2. How can I do this in a smarter way?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

肥爪爪 2024-10-11 19:48:43

与时俱进吧,我的好人!我在 24 小时前就解决了这个问题。接下来,我预计会看到迅猛龙追逐渡渡鸟,一边猛烈地挥动马鞭,一边在点播屏幕保护程序上查找股票报价。

有问题的提交是: http://lampsvn.epfl.ch/trac/scala/changeset /23622

// 1130.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
}

object Test {
  def main(args: Array[String]): Unit = {
    M.accept(M.a)
  }
}

// too old
% /scala/inst/scala-2.9.0.r23619/bin/scalac ./1130.scala 
./1130.scala:15: error: type mismatch;
 found   : Obj[object M]
 required: Obj[M.type]
    M.accept(M.a)
               ^
one error found

// fresh enough
% /scala/inst/scala-2.9.0.r23624/bin/scalac ./1130.scala 
%

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

// 1130.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
}

object Test {
  def main(args: Array[String]): Unit = {
    M.accept(M.a)
  }
}

// too old
% /scala/inst/scala-2.9.0.r23619/bin/scalac ./1130.scala 
./1130.scala:15: error: type mismatch;
 found   : Obj[object M]
 required: Obj[M.type]
    M.accept(M.a)
               ^
one error found

// fresh enough
% /scala/inst/scala-2.9.0.r23624/bin/scalac ./1130.scala 
%
梦过后 2024-10-11 19:48:43

使用 this.type 而不是 M。这个简化的例子应该可以工作:

class Obj[M <: Maker]

class Maker {
  def make() = new Obj[this.type]
  def accept(obj: Obj[this.type]) = println(obj)
}

object M extends Maker

object N extends Maker

M.accept(M.make()) //works!
M.accept(N.make()) //error! type mismatch!

Use this.type instead of M. This simplified example should work:

class Obj[M <: Maker]

class Maker {
  def make() = new Obj[this.type]
  def accept(obj: Obj[this.type]) = println(obj)
}

object M extends Maker

object N extends Maker

M.accept(M.make()) //works!
M.accept(N.make()) //error! type mismatch!
陌伤浅笑 2024-10-11 19:48:43

您的第一个问题,“object com.test.M 的类型是什么,它与 com.test.M.type 有什么不同?”,仍然没有被解决。回答道。我没有在规范中找到它的记录,但似乎 object M 类型是表示定义对象 M 时隐式创建的类的内部类型。当然,M 是该类的唯一实例,因此人们会期望 object M 类型等同于 M.type,但是编译器显然不这么认为。

您遇到的问题,如 @retronym 解释的 的问题是,当您调用 make 方法时,不会为类型参数推断单例类型 M.type。这与在下面的会话中推断 String 而不是 v.type 的原因相同:

scala> val v = "asdf"                      
v: java.lang.String = asdf

scala> identity(v)
res0: java.lang.String  = asdf

其中 identity 定义为

def identity[T](v: T) = v

Your first question, "What's the type object com.test.M, and how is it different from com.test.M.type?", still hasn't been answered. I haven't found it documented in the spec, but it seems that the object M type is the internal type representing the class that is implicitly created when you define an object M. Of course, M is the only instance of that class so one would expect the object M type to be equivalent to M.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 your make method. This is for the same reason that String is inferred rather than v.type in the session below:

scala> val v = "asdf"                      
v: java.lang.String = asdf

scala> identity(v)
res0: java.lang.String  = asdf

where identity is defined as

def identity[T](v: T) = v
阳光下的泡沫是彩色的 2024-10-11 19:48:43

这是有效的:

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.type]
}

M.accept(M.a)

秘密“酱汁”是在单例对象中使用 make[M.type]

@retronym 值得赞扬解释这一点: 如何正确输入-注释这个 HList?

This works:

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.type]
}

M.accept(M.a)

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?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文