将方法注入到现有类中
我想找到一种方法在 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)的错误吗?
I want to come out a way to define a new method in some existing class in scala.
For example, I think the asInstanceOf[T]
method has too long a name, I want to replace it with as[T].
A straight forward approach can be:
class WrappedAny(val a: Any) {
def as[T] = a.asInstanceOf[T]
}
implicit def wrappingAny(a: Any): WrappedAny = new WrappedAny(a)
Is there a more natural way with less code?
Also, a strange thing happens when I try this:
scala> class A
defined class A
scala> implicit def toA(x: Any): A = x
toA: (x: Any)A
scala> toA(1)
And the console hang. It seems that toA(Any)
should not pass the type checking phase, and it can't when it's not implicit. And putting all the code into a external source code can produce the same problem. How did this happen? Is it a bug of the compiler(version 2.8.0)?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
从技术上讲,你拉皮条
Any
的方法没有任何问题,尽管我认为这通常是不明智的。同样,asInstanceOf
和isInstanceOf
的命名如此冗长也是有原因的;这是为了阻止您使用它们!几乎可以肯定,有一种更好的、静态类型安全的方法来完成您想要做的任何事情。关于导致控制台挂起的示例:
toA
的声明类型为Any => A
,但您已将其结果定义为x
,其类型为Any
,而不是A
。这怎么可能编译?好吧,请记住,当发生明显的类型错误时,编译器会四处寻找任何可用的隐式转换来解决问题。在这种情况下,它需要隐式转换Any => A
...并找到一个:toA
!所以toA
类型检查的原因是因为编译器隐式地将其重新定义为:...当您尝试使用它时,这当然会导致无限递归。
There's nothing technically wrong with your approach to pimping
Any
, although I think it's generally ill-advised. Likewise, there's a reasonasInstanceOf
andisInstanceOf
are so verbosely named; it's to discourage you from using them! There's almost certainly a better, statically type-safe way to do whatever you're trying to do.Regarding the example which causes your console to hang: the declared type of
toA
isAny => A
, yet you've defined its result asx
, which has typeAny
, notA
. How can this possibly compile? Well, remember that when an apparent type error occurs, the compiler looks around for any available implicit conversions to resolve the problem. In this case, it needs an implicit conversionAny => A
... and finds one:toA
! So the reasontoA
type checks is because the compiler is implicitly redefining it as:... which of course results in infinite recursion when you try to use it.
在第二个示例中,您将
Any
传递给必须返回A
的函数。但是,它永远不会返回A
,而是返回您传入的相同Any
。然后,编译器会尝试应用隐式转换,而隐式转换又不会返回A
> 但任何
,等等。如果您将 toA 定义为非隐式,您将得到:
In your second example you are passing
Any
to a function that must returnA
. However it never returnsA
but the sameAny
you passed in. The compiler then tries to apply the implicit conversion which in turn does not return anA
butAny
, and so on.If you define toA as not being implicit you get:
碰巧的是,这个问题之前已经在 Scala 列表中讨论过。皮条客我的类模式确实有点冗长,也许,可能有一种方法可以在不引入新关键字的情况下清理语法。
关于新关键字的一点是,Scala 的目标之一是通过库使语言可扩展,而不是将语言变成一大堆想法,通过某人的“有用到足以添加到语言中”的标准,同时,时间,使其他想法变得不可能,因为它们被认为不够有用和/或不够普遍。
不管怎样,到目前为止还没有任何进展,我也没有听说有任何工作正在朝着这个目标进行。欢迎您通过邮件列表加入社区并为其发展做出贡献。
As it happens, this has been discussed on Scala lists before. The pimp my class pattern is indeed a bit verbose for what it does, and, perhaps, there might be a way to clean the syntax without introducing new keywords.
The bit about new keywords is that one of Scala goals is to make the language scalable through libraries, instead of turning the language into a giant quilt of ideas that passed someone's criteria for "useful enough to add to the language" and, at the same time, making other ideas impossible because they weren't deemed useful and/or common enough.
Anyway, nothing so far has come up, and I haven't heard that there is any work in progress towards that goal. You are welcome to join the community through its mailing lists and contribute to its development.