给定某种路径相关类型的值,如何获取“容器”的实例?

发布于 2024-10-16 14:24:22 字数 374 浏览 0 评论 0原文

用代码更容易解​​释:

class Bippy {
  val x = 42

  class Boppy {
    val y = "hello world"
  }

  val bop = new Boppy
}

val bip = new Bippy
val bop: Bippy#Boppy = bip.bop

bop 然后被提供给另一个方法,该方法需要从包含 Bippy 的实例中查找值 x。有什么神奇的咒语可以做到这一点?

实例 bop 来自我无法控制的代码,因此此处无法向 Boppy 添加新方法。

It's more easily explained in code:

class Bippy {
  val x = 42

  class Boppy {
    val y = "hello world"
  }

  val bop = new Boppy
}

val bip = new Bippy
val bop: Bippy#Boppy = bip.bop

bop is then supplied to another method, which needs to find the value x from the containing instance of Bippy. What's the magic incantation to do so?

The instance bop comes from code that I don't control, so adding new methods to Boppy isn't an option here.

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

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

发布评论

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

评论(2

睫毛溺水了 2024-10-23 14:24:22

你不能。至少不是没有作弊。以下是如何作弊。

def getOuter(bop : Bippy#Boppy) = 
   bop.asInstanceOf[{def Bippy$Boppy$$outer() : Bippy}].Bippy$Boppy$$outer()

显然,这很大程度上取决于 scalac 今天如何工作的细节,并且不能保证它明天也能工作。

You can't. At least not without cheating. Here's how to cheat.

def getOuter(bop : Bippy#Boppy) = 
   bop.asInstanceOf[{def Bippy$Boppy$$outer() : Bippy}].Bippy$Boppy$$outer()

Obviously that's very dependent on details of how scalac works today and no guarantees that it will work tomorrow.

百变从容 2024-10-23 14:24:22

正如詹姆斯所说,你不能。他的作弊让我眼睛流血,我建议做点别的事情来代替;-)

我强烈建议如果可以的话修改 bop 的消费者。不要向他们提供 Bippy#Boppy 的实例,而是向他们提供一对由依赖类型的值和该类型所依赖的值组成的对,

trait DependentPack {
  val bippy : Bippy
  val boppy : bippy.Boppy
}

val bip = new Bippy
val bop = bip.bop
val dep = new DependentPack { val bippy = bip ; val boppy = bop }
foo(dep)

def foo(dp : DependentPack) = {
  import dp._
  // use bippy ...
  // use boppy ...
}

请注意,这在一定程度上是针对缺乏依赖方法类型的解决方法(在 scalac 中启用)通过添加 -Ydependent-method-types 或 -Xexperimental 命令行开关)。如果我们拥有它们,那么我们可以删除像 DependentPack 这样的工件并重写上面的内容,

val bip = new Bippy
val bop = bip.bop
foo(bip)(bop)

def foo(bippy : Bippy)(boppy : bippy.Boppy) = {
  // use bippy ...
  // use boppy ...
}

不用说,我认为默认启用依赖方法类型将是非常可取的。除非您非常小心,否则依赖类型的重要使用会在缺少它们时带来巨大的痛苦。

As James said, you can't. His cheat makes my eyes bleed, and I suggest doing something else instead ;-)

I strongly recommend modifying the consumers of bop if you can. Rather than handing them an instance of Bippy#Boppy, hand them a pair comprising the value of the dependent type and the value that the type depends on,

trait DependentPack {
  val bippy : Bippy
  val boppy : bippy.Boppy
}

val bip = new Bippy
val bop = bip.bop
val dep = new DependentPack { val bippy = bip ; val boppy = bop }
foo(dep)

def foo(dp : DependentPack) = {
  import dp._
  // use bippy ...
  // use boppy ...
}

Note that this is in part a workaround for the lack of dependent method types (enabled in scalac by adding the -Ydependent-method-types or -Xexperimental command line switches). If we had them, then we could drop artefacts like DependentPack and rewrite the above as,

val bip = new Bippy
val bop = bip.bop
foo(bip)(bop)

def foo(bippy : Bippy)(boppy : bippy.Boppy) = {
  // use bippy ...
  // use boppy ...
}

Needless to say, I think having dependent method types enabled by default would be highly desirable. Non-trivial uses of dependent types bring a world of pain with them in their absence unless you're very careful.

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