【问题标题】:scala: have constructor distinguish between apply and implicit parameter?scala:构造函数区分应用和隐式参数吗?
【发布时间】:2011-05-20 16:33:26
【问题描述】:

我有这样的课:

class A(arg: Int)(implicit i: Boolean) {
  def apply(v: Double): this.type = {
    // do stuff
    this
  }
}

我想通过在同一行初始化和调用 apply 来创建它的实例:

implicit val i = false
val a = A(arg=1)(v=2.0) // doesn't work
val a2 = (A(arg=1))(v=2.0) // doesn't work

不幸的是,编译器假定 v=2.0 用于隐式参数,而不是用于 apply()。我尝试了多种插入 {} 和 () 的不同语法,但都没有奏效。我意识到 v 可以移动到构造函数中,但在我的情况下,这不是一个选项,因为 A 是子类,我不想将 v 添加到每个子类构造函数中。有没有办法做到这一点?谢谢。

【问题讨论】:

  • @pst 试过了,由于某种原因不起作用
  • A(1)|>(_(2.0)) ...好吧,可能不会更好。

标签: scala


【解决方案1】:

“丑陋但似乎有效”怎么样......

class A(arg: Int)(implicit i: Boolean) {
  def apply(v: Double): this.type = this
}
implicit val i = false
// removing the :A makes this fail to run on simplyscala
val a1 = (new A(arg=1) : A)(v=2.0)
// also works with explicit method name
val a2 = new A(arg=1).apply(v=2.0)
// and works without implicit being ... implicitized
val a = new A(arg=1)(i)(v=2.0)

老实说,不知道 :-) 但是,考虑一下这可能是一些见解:

val a = (new A(arg=1))(2.0)
错误:类型不匹配;
 发现:双(2.0)
 必需:布尔值
       val a = (new A(arg=1))(2.0)

哇!

编码愉快。

【讨论】:

    【解决方案2】:

    (我假设您在伴生对象中有一个构造方法,因为您没有使用new A。)

    一个选项是写在两行:

    val atmp = A(1)
    val a = atmp(2.0)
    

    ……但这肯定不是你想要的。另一个同样令人不满意的选择是

    val a = A(1)(implicitly)(2.0)
    

    如果你能忍受的话。也许最不难看的方法是显式调用apply

    val a = A(1).apply(2.0)
    

    最后,你可以向伴生对象添加一个新的构造方法来处理这一切:

    object A {
      def apply(arg: Int, v: Double)(implicit i: Boolean) = A(arg)(i)(v)
    }
    
    val a = A(1, 2.0)
    

    【讨论】:

    • 我喜欢选项 2,因为它比 apply 更明确一点,而且因为这两种方法都更明确......
    猜你喜欢
    • 1970-01-01
    • 2023-03-06
    • 1970-01-01
    • 1970-01-01
    • 2023-03-17
    • 2016-03-12
    • 2020-02-13
    • 1970-01-01
    相关资源
    最近更新 更多