【问题标题】:Accounting for type parameters in a Scala generic class 'equals' method... are manifests the only way?在 Scala 泛型类“equals”方法中考虑类型参数......是唯一的方法吗?
【发布时间】:2010-07-19 18:27:11
【问题描述】:

给定一个简单的泛型类:

class EqualsQuestion[T]( val value :T )

以下代码解析为“false”似乎是合理的:

val a = new EqualsQuestion[Int]( 5 )
val b = new EqualsQuestion[Long]( 5 )
a == b

(是的,这是一个人为的例子。在我的真实代码中,如果类型参数不同,无论值是否相同,我都希望 '==' 失败,尽管此时我不确定这是否有意义. 尽管如此,它还是让我觉得这是一个有趣的 Scala 问题。)

反正我当然没能实现这样的equals()方法:

override def equals( obj :Any ) :Boolean = 
{
    obj match {
        case that :EqualsQuestion[T] => 
                ( this.getClass == that.getClass ) &&  // no help
                this.getClass().isInstance(that) && // no help
                //this.value.getClass == that.value.getClass && // doesn't even compile
                this.value == that.value

        case _ => false
    }
}

问题是类型擦除,我知道:此时所有编译器都知道 'T' 是一种类型,但它不知道该类型是什么。所以无法进行比较。

似乎 2.8 可以通过清单解决这个问题,但是......我不太明白 How do I get around type erasure on Scala? Or, why can't I get the type parameter of my collections? 的意思。

还有其他方法吗?

【问题讨论】:

  • EqualsQuestion 的擦除是您从任何实例上的 getClass 调用中得到的(不管T 绑定到什么),所以当您将obj 与@ 匹配时987654327@ 你知道that.getClass 将与getClass 相同。

标签: generics scala


【解决方案1】:

下面这个函数好像可以区分a和b:

def same(x: EqualsQuestion[_], y: EqualsQuestion[_]) = {
  x.value.asInstanceOf[AnyRef].getClass == y.value.asInstanceOf[AnyRef].getClass && 
  x.value == y.value
}

请注意,这仅在 T 本身不是泛型类型时才有效,例如它不会区分 List[Int] 和 List[Long]。我希望这已经足够好了......

【讨论】:

  • 啊!强制转换为最低级别以使编译器满意,然后运行时可以执行 getClass 调用。聪明的! :-)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-08-20
  • 1970-01-01
  • 2012-09-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-05-08
相关资源
最近更新 更多