如何使用伴随工厂对象作为策略?

发布于 2024-12-11 13:48:21 字数 621 浏览 0 评论 0原文

我有一个测试,当我迭代 Map 中的值时,由于排序问题而间歇性失败。

Scala 提供了一个 ListMap,它可以使测试稳定,但会牺牲性能。因此,我将 ImmutableMapFactory 抽象为 val 并在我的代码中使用它。

class C {
  val immutableMapFactory = scala.collection.immutable.Map

  def func = {
    ...
    immutableMapFactory(pairs :_*)
  }
}

现在我的计划是扩展 C 并覆盖 immutableMapFactory 进行测试,

class TestableC extends C {
  override val immutableMapFactory = scala.collection.immutable.ListMap
}

这并不奇怪,因为 ListMapMap 的类型不同。我应该如何指定 val (或 def)的类型,以便我可以在需要创建 Map 的任何地方使用工厂?

I have a test which fails intermittently because of ordering issues when I iterate over the values in a Map.

Scala helpfully provides a ListMap which makes the tests stable, at the expense of performance. So I abstracted the ImmutableMapFactory as a val and use it in my code.

class C {
  val immutableMapFactory = scala.collection.immutable.Map

  def func = {
    ...
    immutableMapFactory(pairs :_*)
  }
}

Now my plan was to extend C and override immutableMapFactory for tests

class TestableC extends C {
  override val immutableMapFactory = scala.collection.immutable.ListMap
}

Unsurprising this fails as ListMap does not have the same type as Map. How should I specify the type of the val (or a def) so that I can use the factory wherever I need to create a Map?

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

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

发布评论

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

评论(2

半城柳色半声笛 2024-12-18 13:48:21

两种可能的方式。首先,使用 def 和函数,我认为这是一个更好的抽象。

class C {
  def immutableMapFactory[A,B]: ((A,B)*) => Map[A,B] = scala.collection.immutable.Map.apply _
}

class TestableC extends C {
  override def immutableMapFactory[A,B] = scala.collection.immutable.ListMap.apply _
}

其次,使用 val 和结构类型:

class C {
  val immutableMapFactory: { def apply[A,B](t: (A,B)*): Map[A,B] } = scala.collection.immutable.Map
}

class TestableC extends C {
  override val immutableMapFactory: { def apply[A,B](t: (A,B)*): Map[A,B] } = scala.collection.immutable.ListMap
}

Two possible ways. First, using def and functions, which I think is a better abstraction.

class C {
  def immutableMapFactory[A,B]: ((A,B)*) => Map[A,B] = scala.collection.immutable.Map.apply _
}

class TestableC extends C {
  override def immutableMapFactory[A,B] = scala.collection.immutable.ListMap.apply _
}

Second, using val, and structural types:

class C {
  val immutableMapFactory: { def apply[A,B](t: (A,B)*): Map[A,B] } = scala.collection.immutable.Map
}

class TestableC extends C {
  override val immutableMapFactory: { def apply[A,B](t: (A,B)*): Map[A,B] } = scala.collection.immutable.ListMap
}
几味少女 2024-12-18 13:48:21

您的问题在于这一行:

val immutableMapFactory = scala.collection.immutable.Map

这使得 immutableMapFactory 等于单例对象 MapListMap(单例)不是Map(单例)的子类,因此后续重写失败。

如果您从 Map 中获取 apply 方法,并部分应用它来形成第一类函数(类型为 (A, B)* => 不可变的) .Map[A,B]) 那么该技术就可以发挥作用:

import collection.immutable

class Bip {
  def fac[A,B] = immutable.Map.apply[A,B] _
}

class Bop extends Bip {
  override def fac[A,B] = immutable.ListMap.apply[A,B] _
}

Your problem is in this line:

val immutableMapFactory = scala.collection.immutable.Map

This makes immutableMapFactory equal to the singleton object Map. ListMap (the singleton) is not a subclass of Map (the singleton), so the subsequent override fails.

If you instead take the apply method from Map, and partially apply it to form a first class function (of type (A, B)* => immutable.Map[A,B]) then the technique can be made to work:

import collection.immutable

class Bip {
  def fac[A,B] = immutable.Map.apply[A,B] _
}

class Bop extends Bip {
  override def fac[A,B] = immutable.ListMap.apply[A,B] _
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文