将方法注入现有类

时间:2010-11-18 09:22:01

标签: scala

我想找到一种方法来在scala中的某个现有类中定义一个新方法。

例如,我认为asInstanceOf[T]方法名称太长,我想用as[T].替换它

直接的方法可以是:

class WrappedAny(val a: Any) {
  def as[T] = a.asInstanceOf[T]
}

implicit def wrappingAny(a: Any): WrappedAny = new WrappedAny(a)

使用更少的代码是否有更自然的方式?

另外,当我尝试这个时,会发生一件奇怪的事情:

scala> class A

defined class A

scala> implicit def toA(x: Any): A = x

toA: (x: Any)A

scala> toA(1)

控制台挂了。似乎toA(Any)不应该通过类型检查阶段,并且当它不是隐式时它不能。将所有代码放入外部源代码可能会产生同样的问题。这怎么发生的?这是编译器的错误(版本2.8.0)吗?

3 个答案:

答案 0 :(得分:8)

你对拉皮条Any的方法没有任何技术上的错误,尽管我认为这通常是不明智的。同样地,asInstanceOfisInstanceOf如此详细地命名是有原因的;这是为了阻止你使用它们!几乎可以肯定,这是一种更好的,静态类型安全的方式来做任何你想做的事情。

关于导致控制台挂起的示例:声明的toA类型为Any => A,但您已将其结果定义为x,其类型为Any },而不是A。这怎么可能编译?好吧,请记住,当出现明显的类型错误时,编译器会四处寻找任何可用的隐式转换来解决问题。在这种情况下,它需要隐式转换Any => A ...并找到一个:toA!因此toA类型检查的原因是因为编译器隐式地将其重新定义为:

implicit def toA(x: Any): A = toA(x)

...当你尝试使用它时,当然会导致无限递归。

答案 1 :(得分:3)

在第二个示例中,您将Any传递给必须返回A的函数。但是它永远不会返回A但是传入的Any相同。然后编译器尝试应用隐式转换,而隐式转换又不返回A而是Any,并且等等。

如果您将toA定义为不隐式,则得到:

scala> def toA(x: Any): A = x           
<console>:6: error: type mismatch;
 found   : Any
 required: A
       def toA(x: Any): A = x
                            ^

答案 2 :(得分:1)

实际上,之前已经在Scala列表中对此进行了讨论。 pimp我的类模式确实有点冗长,也许,可能有一种方法可以在不引入新关键字的情况下清理语法。

关于新关键字的一点是,Scala的目标之一是通过库使语言可扩展,而不是将语言变成一个巨大的想法,这些想法通过某人的标准“足够有用,可以添加到语言中”,同时,让其他想法变得不可能,因为它们被认为不合适和/或不够普遍。

无论如何,到目前为止还没有任何结果,我还没有听说有任何进展正在朝着这个目标前进。欢迎您通过其邮件列表加入社区,并为其发展做出贡献。