2012-06-22 30 views
56

Trong khi tìm kiếm một cái gì đó khác, khá ra khỏi sự trùng hợp ngẫu nhiên, tôi tình cờ gặp vài lời bình luận về cách thức thừa kế lớp vỏ não. Có điều này được gọi là ProductN, wretches và vua, yêu tinh và pháp sư và làm thế nào một số loại tài sản rất mong muốn bị mất với trường hợp thừa kế các trường hợp. Vì vậy, những gì là sai trái với trường hợp thừa kế lớp?Lỗi * so * với trường hợp thừa kế lớp là gì?

Trả lời

97

Một từ: bình đẳng

case lớp đi kèm với việc thực hiện cung cấp của equalshashCode. Mối quan hệ tương đương, được gọi là equals hoạt động như thế này (nghĩa là phải có các thuộc tính sau):

  1. Đối với tất cả x; x equals xtrue (phản xạ)
  2. Đối với x, y, z; nếu x equals yy equals z thì x equals z (chuyển tiếp)
  3. Đối với x, y; nếu x equals y sau đó y equals x (đối xứng)

Ngay sau khi bạn cho phép bình đẳng trong một hệ thống phân cấp thừa kế, bạn có thể phá vỡ 2 và 3. Đây là trivially chứng minh bằng ví dụ sau:

case class Point(x: Int, y: Int) 
case class ColoredPoint(x: Int, y: Int, c: Color) extends Point(x, y) 

Sau đó, chúng tôi có :

Point(0, 0) equals ColoredPoint(0, 0, RED) 

Nhưng không

ColoredPoint(0, 0, RED) equals Point(0, 0) 

Bạn có thể tranh luận rằng tất cả các cấu trúc phân lớp có thể có vấn đề này và điều này là đúng. Nhưng các trường hợp đặc biệt tồn tại để đơn giản hóa bình đẳng từ góc nhìn của nhà phát triển (trong số các lý do khác), do đó, để chúng hoạt động không trực quan sẽ là định nghĩa của một mục tiêu riêng!


Cũng có những lý do khác; đáng chú ý là thực tế là copy did not work as expectedinteraction with the pattern matcher.

+0

Và còn một chút công phu nữa :)? –

+2

Có vẻ như sự tương đương không đối xứng như vậy sẽ là một điều hữu ích trong mô hình OO, theo cách tương tự ở cấp độ kiểu 'Màu 'là một' Điểm 'nhưng không ngược lại. Có thể phải gọi nó là một cái gì đó khác hơn là 'bằng' mặc dù ... có lẽ 'subEquals'? –

+0

@LuigiPlinge có lẽ 'canReplace',' supersedes', 'chỉ định' hoặc' ghi đè' cho mối quan hệ ngược lại? Bất cứ điều gì để chỉ ra '> =' -ness (hoặc '>:' nếu bạn thích) của nó. Nó có vẻ dễ dàng hơn nhiều cho tôi để đặt tên nó về '> =' chứ không phải là '<='. –

-2

Điều đó không đúng. Và điều này còn tệ hơn là nói dối.

Như đã đề cập bởi aepurniet trong bất kỳ trường hợp lớp người kế đó co lại một khu vực xác định phải xác định lại sự bình đẳng vì khớp mẫu phải làm việc chính xác như bình đẳng (nếu cố gắng để phù hợp với Point như ColoredPoint thì nó sẽ không xuất hiện kể từ khi color là không tồn tại).

Điều đó cung cấp cho sự hiểu biết về mức độ bình đẳng của phân cấp lớp vỏ có thể được triển khai.

case class Point(x: Int, y: Int) 
case class ColoredPoint(x: Int, y: Int, c: Color) extends Point(x, y) 

Point(0, 0) equals ColoredPoint(0, 0, RED) // false 
Point(0, 0) equals ColoredPoint(0, 0, null) // true 

ColoredPoint(0, 0, RED) equals Point(0, 0) // false 
ColoredPoint(0, 0, null) equals Point(0, 0) // true 

Cuối cùng, bạn có thể đáp ứng các yêu cầu của mối quan hệ bình đẳng ngay cả đối với người kế thừa trường hợp (không ghi đè bình đẳng).

case class ColoredPoint(x: Int, y: Int, c: String) 
class RedPoint(x: Int, y: Int) extends ColoredPoint(x, y, "red") 
class GreenPoint(x: Int, y: Int) extends ColoredPoint(x, y, "green") 

val colored = ColoredPoint(0, 0, "red") 
val red1 = new RedPoint(0, 0) 
val red2 = new RedPoint(0, 0) 
val green = new GreenPoint(0, 0) 

red1 equals colored // true 
red2 equals colored // true 
red1 equals red2 // true 

colored equals green // false 
red1 equals green // false 
red2 equals green // false 

def foo(p: GreenPoint) = ??? 
Các vấn đề liên quan