【问题标题】:Why implicitConversions is required for implicit defs but not classes?为什么隐式defs需要implicitConversions而不是类?
【发布时间】:2013-09-25 17:51:29
【问题描述】:

据我了解,隐式转换可能会导致代码难以理解,或者代码存在其他问题(甚至可能是错误?),这就是为什么它们需要显式启用才能在代码中使用而不会收到警告.

但是,鉴于隐式转换在很大程度上(如果不是大部分时间)用于用另一种类型的对象包装对象,隐式类也是如此 - 如果我是,我会很感激你纠正我错了——为什么前者需要导入scala.language.implicitConversions,而后者不需要?

object Main extends App {
  implicit class StringFoo(x: String) {
    def fooWithImplicitClass(): Unit =
      println("foo with implicit class")
  }
  // => silence.

  "asd".fooWithImplicitClass()

  /************************/

  class Foo(x: String) {
    def fooWithImplicitDef(): Unit =
      println("foo with implicit def")
  }
  implicit def string2Foo(x: String) = new Foo(x)
  // => warning: implicit conversion method string2Foo should be enabled

  "asd".fooWithImplicitDef()
}

【问题讨论】:

    标签: scala type-conversion implicit-conversion


    【解决方案1】:

    隐式类实际上只添加新方法(或特征),并且仅在调用这些添加的方法时才使用它们(或显式使用隐式类,但这在实践中很少发生)。另一方面,对现有类型的隐式转换可以在程序员不可见的情况下调用。

    【讨论】:

    • 你的意思是不是因为隐式转换不仅在使用“原始”类型中不存在的方法时起作用,而且在请求“隐式类型”的对象时,例如当传递TypeA 而不是TypeB 并且存在转换TypeA -> TypeB 时?
    • @RégisJean-Gilles:Alexey 的意思是 StringFoo 是一种专门用于使用额外方法修改现有类型的类型,而隐式转换允许从类型 A 转换为一个完全不相关的B,没有专门为此目的创建的B。 (但我现在还在看是否会出现更好的解释)
    • @Erik REPL 中的一个快速实验表明隐式类执行相同的转换,所以我不理解这个论点ideone.com/m025gQ
    • 所以,如果我理解正确,这里的论点是隐式转换(一般意义上的)更大的多功能性(因此更大的风险面)?如果是这样,可以说编译器可以(应该?)避免发出警告,如果所述隐式转换被定义在与其转换到的类相同的范围内(假设在这种情况下,我们处于与使用隐式类时)。我想不分青红皂白地发出警告更容易。
    • @RégisJean-Gilles 我同意在这种情况下不需要发出警告。另一方面,我也认为对扩展其他类实现特征的隐式类发出警告是有意义的,因为它们也是对预先存在的类型的转换。我猜它被忽略了,因为这样的隐式类很少见(我从未见过),但它们是合法的。
    【解决方案2】:

    IMO,就可能引起的混淆而言,隐式类和隐式转换之间没有根本区别,因此两者都应该被警告。

    但是通过将一个类定义为隐式,这就像通过告诉编译器“我是成年人,我知道我在做什么”来明确地抑制警告。这个类打算以这种方式使用(可能作为扩展包装)。”因此,不会发出警告,因为作为类的创建者,您已经明确表示,隐式使用是该类应该如何工作或允许使用该类的方式,编译器当然应该信任您。

    另一方面,您可以通过使用隐式转换将对象转换为任何类,无论目标类是否打算被隐式使用。这是许多麻烦的根源,也是 Scala 试图阻止的。

    【讨论】:

    • 该参数的问题在于,被转换为不需要的类需要在either情况下被定义为隐式。例如:ideone.com/1wwCoA
    • 但我认为在您提供的代码示例中,该字符串已转换为StringToFoo,对吗? ideone.com/sBKryP
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-23
    • 1970-01-01
    • 1970-01-01
    • 2018-03-18
    • 1970-01-01
    相关资源
    最近更新 更多