代码之家  ›  专栏  ›  技术社区  ›  devoured elysium

scala允许任意实例化泛型对象吗?新的B{}?

  •  4
  • devoured elysium  · 技术社区  · 6 年前

    我想知道这样的东西是否可以在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,所以我无法控制它)。 最明显的方法就是通过继承。有什么办法吗?

    2 回复  |  直到 6 年前
        1
  •  4
  •   Alexey Romanov    6 年前

    布莱恩回答了标题中的问题(你也可以考虑 B 可以有你不知道要定义的抽象方法)。但是

    我希望能够重新定义给我的任意对象的equals/hashcode

    建议使用不同的签名:

    def f[B <: AnyRef](x: 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
    }
    
        2
  •  5
  •   Brian McCutchon    6 年前

    这在一般情况下是绝对不可能的。

    假设我通过了 sealed 类型为 B ,如 String . 没有办法将其子类化。所以,你不能随意地这么做 .

    根据其他框架的工作方式,您可能能够通过 AnyRef 相反。否则,您可能可以使用宏实现某些功能,但需要更多信息来确定这一点。

    推荐文章