我想知道这样的事情是否可以在Scala中实现:
def f[B <: AnyRef]()(implicit ct: ClassTag[B]): B = {
new B {
override def equals(o: Any) = ...
override def hashcode(o: Any) = ...
}
}
我的直觉是,即使使用ClassTag
,也应该无法实例化任意B
,因为我们不知道它甚至没有no-args参数。
但是我得到的实际错误是:
class type required but B found
我当前的用例是:我希望能够重新定义提供给我的任意对象的equals / hashcode(我无法逃避,因为我必须将这些对象传递给某些对象将使用这些对象的equals / hashcodes的错误框架,因此我对此无能为力)。 显而易见的方法是通过继承。有什么办法吗?
答案 0 :(得分:5)
在一般情况下绝对不可能。
假设我为final
传递了B
类型,例如String
。没有办法将其子类化。因此,您不能对任意B
这样做。
根据其他框架的工作方式,您也许可以将其传递给AnyRef
。否则,您也许可以使用宏完成一些工作,但是需要更多信息来确定这一点。
答案 1 :(得分:4)
Brian回答了标题中的问题(您也可以考虑B
可以使用您不知道定义的抽象方法)。但是
我希望能够重新定义提供给我的任意对象的equals / hashcode
建议使用其他签名:
def f[B <: AnyRef](x: B): B = ...
,这一个 是可行的。当然有限制。如果B
是接口,则可以使用dynamic proxies from Java standard library,
对于类,您需要一个CGLIB之类的库。大约(未试用):
def f[B <: AnyRef](x: B): B = {
val enhancer = new Enhancer()
enhancer.setSuperclass(x.getClass)
val interceptor: MethodInterceptor = (obj, method, args, proxy) =>
method.getName match {
case "equals" => // your equals impl
case "hashCode" => // your hashCode impl
case _ => proxy.invokeSuper(obj, args)
}
enhancer.setCallback(interceptor)
enhancer.create() as B
}