Scala 相等和有序[T]的继承(类层次结构)(类型参数擦除)

Scala 相等和有序[T]的继承(类层次结构)(类型参数擦除),scala,pattern-matching,type-erasure,Scala,Pattern Matching,Type Erasure,我希望有几个数据类,它们都有一个指定为 足以检查对象相等性。 但是这个id:I不仅应该用于测试 平等的,但也是为了比较的目的。 这就是为什么视图绑定I为false } } /*应与所有其他真实的*/ val y12=新的YetAnotherIntId(12) val y13=新的YetAnotherIntId(13) y12 canEqual y13/*=>真*/ y12真*/ i12 canEqual y12/*=>正确*/ y12 canEqual i12/*=>假*/ i12==y12/*

我希望有几个数据类,它们都有一个指定为 足以检查对象相等性。 但是这个
id:I
不仅应该用于测试 平等的,但也是为了比较的目的。 这就是为什么视图绑定
I为false
}
}
/*应与所有其他真实的*/
val y12=新的YetAnotherIntId(12)
val y13=新的YetAnotherIntId(13)
y12 canEqual y13/*=>真*/
y12真*/
i12 canEqual y12/*=>正确*/
y12 canEqual i12/*=>假*/
i12==y12/*=>false*/
y12==i12/*=>false*/
val j12=新长型(12L)
val j13=新长形(13L)
j12 canEqual j13/*=>正确*/
j12正确*/
i12 canEqual j12/*=>为true,但希望为false,因为Int!=长的*/
j12 canEqual i12/*=>正确“*/
i12==j12/*=>true“”*/
j12==i12/*=>true“”*/
val s12=新的字符串ID(“12”)
val s13=新的StringId(“13”)
s12 canEqual s13/*=>正确*/
s12真*/
i12 canEqual s12/*=>为true,但希望为false,因为Int!=串*/
s12 canEqual i12/*=>真“*/
i12==s12/*=>false*/
s12==i12/*=>false*/
谢谢你,如果你已经读了这么多,但是现在问题是:

我如何才能实现
Ident[I].canEqual(Ident[J])
is
false
for
I!=J
不覆盖
canEqual
YetAnotherIntId
中那样

一个
Ident[I]
似乎是一个
Ident[J]
是一个
Ident[]
,当使用
this.id
that.id
时,通过在
Ident::canEqual
中注释掉,会产生问题(将
true
替换为
this.idthat.id | this.id==that.id


那么,为什么
Ident[Int].canEqual(Ident[Long])
true
?是因为类型擦除吗?是否有可能用
清单来“修复”这一点?或者是否有另一种可能性来确保
I==J

确实是类型擦除。您的
案例中一定有一些警告:Ident[I]
。它检查您是否有一个
标识[somehing]
,但不检查这个东西是否是
I
(与java中相同)。 最好使用
检查:Ident[\u]
中没有错误保证的地方

您的类中可能确实有一个
清单
,并检查清单是否相等

class Ident[I <% Ordered](val id: I)(implicit val manifest: Manifest[I])
  def canEqual(that: Any) = that match {
    case Ident[_] if this.manifest == that.manifest => ...
    case _ => false
  }
}
class Ident[I。。。
大小写=>false
}
}
我建议
I:Ordering
而不是
I%Ordering
(一般来说,不仅仅是为了你的问题)。然后你可以比较订单,而不是清单。你也应该用它在ID上做相等的操作,这样你就知道它与订单是一致的

编辑您的评论


我认为这和拥有相同的
排序
就足以说
canEqual
真的
。然后,你就有了
这个.排序
,编译器知道它是一个
排序[I]
那。排序
这是编译器不知道的类型的排序。您必须使用第一个,这将意味着该.id对I的未检查强制转换(模式匹配或其他)。但是,检查排序相等性应足以确保强制转换是安全的(
排序
是不变的)关于迪迪尔德的回答,他尝试使用一个
隐式ord:Ordering[I]
替换其他必要的
清单
,以确保类型兼容性

abstract class Ident[I](val id: I, dom: String = "")(implicit val ord: Ordering[I])
  extends Equals with Ordered[Ident[I]]
{
  protected val domain: AnyRef = if (dom != "") dom else ord

  override lazy val hashCode = id.##
  def canEqual(other: Any) = other match {
    case that: Ident[_] => this.domain eq that.domain
    case _              => false
  }
  override def equals(other: Any) = other match {
    /* ugly: non variable type-argument I in type pattern Ident[I]
       is unchecked since it is eliminated by erasure */
    case that: Ident[I] if this.domain eq that.domain
           => (that canEqual this) && ord.compare(this.id, that.id) == 0
    case _ => false
  }
  def compare(that: Ident[I]): Int = if (that canEqual this)
    ord compare (this.id, that.id)
  else
  {
    val message = "'%s' and '%s' are not comparable!" format (this, that)
    throw new IllegalArgumentException(message)
  }
  lazy val nameId: String = getClass.getSimpleName + "#" + id
  override def toString = nameId
}
可以创建(子类层次结构),其元素彼此可比

默认情况下,
/*在我的IDE中禁用了订单、子订单和所有其他详细的未检查(擦除)警告。您使用
排序的建议听起来不错,因此尝试修改我的类
类标识[I](val id:I)(隐式val-Order:Ordering[I])
。但是我如何实现
equals
?我已经尝试了
覆盖def equals(other:Any)=other match{case-that:Ident[X]if this.ord==that.ord=>(that canEqual this)和&ord.compare(this.id,that.id==0 case=>false}
我在为X使用
I
时收到擦除警告,但是对于X
,.id
当然不会编译。我可以在
@未选中的情况下抑制警告吗?
/* should be comparable with all other <: Ident[Int] */
class IntId(i: Int) extends Ident[Int](i)
/* should be comparable only with itself */
class YetAnotherIntId(y: Int) extends Ident[Int](y) {
  override def canEqual(other: Any) = other.isInstanceOf[YetAnotherIntId]
  override def equals(other: Any) = other match {
    case that: YetAnotherIntId => super.equals(that)
    case _                     => false
  }
}
/* should be comparable with all other <: Ident[Long] */
class LongId(j: Long) extends Ident[Long](j)
/* should be comparable with all other <: Ident[String] */
class StringId(s: String) extends Ident[String](s)
val i12 = new IntId(12)
val i13 = new IntId(13)
i12 canEqual i13 /* => true */
i12 < i13        /* => true */

val y12 = new YetAnotherIntId(12)
val y13 = new YetAnotherIntId(13)
y12 canEqual y13 /* => true */
y12 < y13        /* => true */

i12 canEqual y12 /* => true */
y12 canEqual i12 /* => false */
i12 == y12       /* => false */
y12 == i12       /* => false */

val j12 = new LongId(12L)
val j13 = new LongId(13L)
j12 canEqual j13 /* => true */
j12 < j13        /* => true */

i12 canEqual j12 /* => true  but want false because Int != Long */
j12 canEqual i12 /* => true  '' */
i12 == j12       /* => true  '' */
j12 == i12       /* => true  '' */

val s12 = new StringId("12")
val s13 = new StringId("13")
s12 canEqual s13 /* => true */
s12 < s13        /* => true */

i12 canEqual s12 /* => true  but want false because Int != String */
s12 canEqual i12 /* => true  '' */
i12 == s12       /* => false */
s12 == i12       /* => false */
class Ident[I <% Ordered](val id: I)(implicit val manifest: Manifest[I])
  def canEqual(that: Any) = that match {
    case Ident[_] if this.manifest == that.manifest => ...
    case _ => false
  }
}
abstract class Ident[I](val id: I, dom: String = "")(implicit val ord: Ordering[I])
  extends Equals with Ordered[Ident[I]]
{
  protected val domain: AnyRef = if (dom != "") dom else ord

  override lazy val hashCode = id.##
  def canEqual(other: Any) = other match {
    case that: Ident[_] => this.domain eq that.domain
    case _              => false
  }
  override def equals(other: Any) = other match {
    /* ugly: non variable type-argument I in type pattern Ident[I]
       is unchecked since it is eliminated by erasure */
    case that: Ident[I] if this.domain eq that.domain
           => (that canEqual this) && ord.compare(this.id, that.id) == 0
    case _ => false
  }
  def compare(that: Ident[I]): Int = if (that canEqual this)
    ord compare (this.id, that.id)
  else
  {
    val message = "'%s' and '%s' are not comparable!" format (this, that)
    throw new IllegalArgumentException(message)
  }
  lazy val nameId: String = getClass.getSimpleName + "#" + id
  override def toString = nameId
}
/* Order, SubOrder and all other <: Ident[Int] without explicit dom are comparable */
class Order(i: Int) extends Ident[Int](i)
class SubOrder(i: Int) extends Order(i)

/* Node and SubNode's are in its own "Node" named domain
   and comparable only among each other */
class Node(i: Int) extends Ident[Int](i, "Node")
class SubNode(i: Int) extends Node(i)