Vấn đề với ví dụ của bạn là bạn chỉ ghi đè phương thức equals
của lớp ẩn danh mà bạn xác định bộ dữ liệu cụ thể của mình là một phần của. Chúng ta hãy xem xét kỹ hơn những gì bạn đang làm khi chạy mã mà bạn đã đưa ra ở đây.
val p = new Pair(1, 2) {
override def equals(obj:Any) = {
obj.isInstanceOf[(Int, Int)] && obj.asInstanceOf[(Int, Int)]._1 == this._1
}
}
gì Scala làm ở đây là nó tạo ra một lớp ẩn danh mới mà mở rộng Pair
và ghi đè bình đẳng của nó. Vì vậy, điều này tương đương với việc chạy mã sau:
class Foo extends Pair(1,2) {
override def equals(obj:Any) = {
obj.isInstanceOf[(Int, Int)] && obj.asInstanceOf[(Int, Int)]._1 == this._1
}
}
val p = new Foo
Và đây là nơi bạn có thể thấy chính xác vị trí của vấn đề! Định nghĩa của equals
không đối xứng. p == (1,1)
đánh giá là true
và (1,1) == p
đánh giá là false
! Điều này là do trước đây là tương đương với p.equals((1,1))
trong khi cái sau tương đương với (1,1).equals(p)
. Trong ví dụ bạn đã đưa ra, nó không hoạt động vì đối tượng trong trường hợp được so sánh với đối tượng được so khớp, và không phải là cách khác xung quanh. Do đó, như bạn đã chỉ ra, Pair.unapply(p).get == (1, 1)
đánh giá là true
, tuy nhiên (1,1) == Pair.unapply(p).get
đánh giá là false
và có vẻ như sau này được sử dụng khi đối sánh.
Tuy nhiên, trong mọi trường hợp tạo một bằng không đối xứng là một ý tưởng thực sự tồi tệ khi thực thi mã phụ thuộc vào thứ tự bạn so sánh các đối tượng. Ngoài ra, bằng bạn đã xác định có vấn đề khác - lỗi không thành công khi bạn cố so sánh p
với bất kỳ Pair
nào là không phải loại (Int, Int)
. Điều này là do, sau khi xóa bỏ loại (đó là cách JVM thực hiện generics), một Pair
không còn được tham số bởi các loại thành phần của nó. Do đó, (Int, Int)
có chính xác cùng loại như (String, String)
và do đó, các mã sau đây sẽ thất bại với lỗi:
p == ("foo", "bar")
như Scala sẽ cố gắng đúc một (String, String)
một (Int, Int)
.
Nếu bạn muốn thực hiện chức năng này, điều đơn giản nhất bạn có thể làm là sử dụng mẫu hình thư viện pimp của tôi, vuốt một Pair
. Tuy nhiên, bạn không nên gọi phương thức của mình equals
. Gọi nó là một cái gì đó khác, như ~=
. Tôi phải đi bây giờ, tuy nhiên khi tôi trở lại tôi có thể cung cấp cho bạn mã cho nó. Nó khá dễ dàng.Bạn nên xem xét việc triển khai equals
trong một cặp và xóa phần so sánh đối số thứ hai :)
Nhưng, mã của tôi đã kiểm tra cả hai hướng đối sánh: T khớp (1, 1) và (1, 1) khớp với T và ít nhất một thành công. – xiefei