加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

scala – (case)类构造函数上下文中的隐式转换

发布时间:2020-12-16 19:18:06 所属栏目:安全 来源:网络整理
导读:我想让自动伴侣类应用案例类的构造函数来为我执行隐式转换,但无法弄清楚如何执行此操作.我一直在搜索,我能找到的最接近的答案是 this问题(我将解释为什么它不是我正在寻找的). 我有一个类似于下面的案例类: case class Container(a: Long,b: Long,c: Long)
我想让自动伴侣类应用案例类的构造函数来为我执行隐式转换,但无法弄清楚如何执行此操作.我一直在搜索,我能找到的最接近的答案是 this问题(我将解释为什么它不是我正在寻找的).

我有一个类似于下面的案例类:

case class Container(a: Long,b: Long,c: Long)

我正在使用容器来计算某些条件适用的实例,所以我希望能够让构造函数自动将布尔参数转换为longs(if(boolean)1L else 0L).

当然,真实的案例类有很多参数,因此制作我自己的伴随对象和重载应用于接受布尔参数会很繁琐且非常重复.此外,类似下面的代码是不理想的(如果它以某种方式正确实现),因为它只接受布尔参数:

object Container {
  def apply(args: Boolean*) = {
    // doesn't REALLY work since number of arguments not enforced
    Container(args map { if (_) 1L else 0L } toArray: _*)
  }
}
val c1 = Container(1,1) // works
val c2 = Container(true,false,true) // might be workable if done correctly
val c3 = Container(true,1) // won't work

我尝试在伴随对象中添加隐式转换(下面),希望它会自动在Container.apply中使用,但看起来这实际上并没有将隐式转换放入调用apply的代码的命名空间中.

object Container {
  implicit def booleanToLong(x: Boolean): Long = if (x) 1L else 0L
}

我能够使用这种hackish变通方法来解决问题:

{
  import Container.booleanToLong
  // all of these now work
  val c1 = Container(1,1)
  val c2 = Container(true,true)
  val c3 = Container(true,1) // works!!!
}

最大的问题是我必须将booleanToLong导入到想要创建Container的代码中,因此必须将其放在自己的块中以确保安全(booleanToLong通常是不合需要的).

最后,使用隐式参数本身包含隐式转换的解决方案不起作用,因为它需要显式覆盖apply,从而违背不重复长参数列表和编组类型的目标.

有没有办法这样做,这样我每次制作一个容器时都可以免费获得隐式转换,但不是这样?或者由于某种技术限制,这是不可能的?

解决方法

您可以使用 magnet pattern的一种变体来使它更安全一些.首先是类型类:

trait ToLong[A] {
  def apply(a: A): Long
}

implicit object longToLong extends ToLong[Long] {
  def apply(l: Long) = l
}

implicit object booleanToLong extends ToLong[Boolean] {
  def apply(b: Boolean) = if (b) 1L else 0L
}

现在我们只需要一个额外的构造函数:

case class Container(a: Long,c: Long)

object Container {
  def apply[A: ToLong,B: ToLong,C: ToLong](a: A,b: B,c: C) = new Container(
    implicitly[ToLong[A]].apply(a),implicitly[ToLong[B]].apply(b),implicitly[ToLong[C]].apply(c)
  )
}

我们可以写下面的内容:

val c1 = Container(1,1)
val c2 = Container(true,true)
val c3 = Container(true,0L,1L)

无需介绍从布尔到Long的相当可怕的一般转换.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读