อย่าง ที่พอจะทราบกันแล้วว่า  ถ้าเราต้องการให้ equals() ของคลาสที่เราเขียนขึ้นเองทำการเปรียบเทียบว่า object เท่ากันหรือไม่ โดยดูจากค่าใน object นั้น แทนที่จะทำการเปรียบเทียบโดยใช้ค่า reference ของ object (คือเปรียบเทียบว่าเป็น object เดียวกันหรือไม่) เราต้องทำการ override equals() พร้อมกับกำหนดวิธีการทำงานแบบที่เราต้องการเอง วิธีการ override equals() อย่างง่าย มีขั้นตอนดังนี้

1. เพิ่ม equals() method declaration เข้าไปในคลาสที่เราเขียนขึ้น ดังนี้

public boolean equals(Object o) {

}

2. ทำการตรวจสอบชนิดของ object ที่รับมาว่าเป็น object ของคลาสที่เราเขียนหรือไม่ โดยใช้ operator instanceof  ถ้า object ที่รับมาไม่ใช่ object ของคลาสที่เราเขียน ให้ return ค่าเป็น false ดังนี้

if (!(o instanceof MyClass))

   return false;

3. ทำการ cast object ที่รับมาให้เป็นชนิดของคลาสที่เราเขียน ดังนี้

MyClass c = (MyClass) o;

4. ทำการเปรียบเทียบค่าแต่ล่ะตัวของ object ทั้งสองว่าเท่ากันหรือไม่ ถ้าค่าเท่ากันให้ return true แต่ถ้าไม่เท่ากันให้ return false ในการเปรียบเทียบค่านั้น มีหลักดังนี้

  • ถ้าค่านั้นเป็นชนิดข้อมูล byte, short, int, long, char ให้ใช้ operator == ในการเปรียบเทียบ
  • ถ้าค่านั้นเป็นชนิดข้อมูล float ให้แปลงค่า float ให้เป็น int ก่อน โดยใช้ Float.floatToIntBits() แล้วเปรียบเทียบค่าที่ได้โดยใช้ operator == อีกที
  • ถ้าค่านั้นเป็นชนิดข้อมูล double ให้แปลงค่า double ให้เป็น long ก่อน โดยใช้ Double.doubleToLongBits() แล้วเปรียบเทียบค่าที่ได้โดยใช้ operator == อีกที
  • ถ้าค่านั้นเป็น object ให้เปรียบเทียบค่าโดยการเรียกใช้ equals() ของคลาสนั้น
  • ถ้าค่านั้นเป็น array ให้ทำการเปรียบเทียบค่าแต่ล่ะตัวภายใน array นั้น โดยใช้หลักการที่อธิบายไว้ข้างต้น

ในการเปรียบเทียบค่าของ object นั้น ให้พยายามเปรียบเทียบค่าที่มีโอกาสไม่เท่ากันมากที่สุดก่อน โดยเรียงลำดับแบบนี้จากมากไปหาน้อย เพราะจะได้ไม่ต้องเสียเวลาเปรียบเทียบค่าอื่น ๆ

5. ตรวจสอบว่าการทำงานของ equals() ที่เรากำหนดขึ้นนั้นเป็นไปตาม general contract หรือสัญญาที่กำหนดไว้ของ equals() หรือไม่  general contract ของ equals() ถูกกำหนดไว้ดังนี้

  • reflexive  สำหรับ object ตัวใดตัวหนึ่ง การเปรียบเทียบกับตัวเองจะต้องเท่ากันเสมอ
  • symmetric สำหรับ object สองตัว x, y ที่นำมาเปรียบเทียบ ถ้า x เท่ากับ y  y จะต้องเท่ากับ x ด้วย
  • transitive สำหรับ object สามตัว x, y, z ที่นำมาเปรียบเทียบกัน ถ้า x เท่ากับ y และ y เท่ากับ z แล้ว x จะต้องเท่ากับ z ด้วย
  • consistent ในการเรียกใช้งาน equals() หลาย ๆ ครั้ง ผลลัพท์ที่ได้จะต้องเหมือนเดิม ถ้าค่าของ object นั้นไม่มีการเปลี่ยนแปลง
  • ถ้าเปรียบเทียบ object กับ null จะต้องได้ false เสมอ

สังเกตว่าคุณสมบัติ reflexive, symmetic และ transitive เป็นคุณสมบัติของสิ่งที่เรียกในทางคณิตศาสตร์ว่า equivalence relation

6. เมื่อไหร่ก็ตามที่เราทำการ override equals() เราจะต้องทำการ override hashCode() ด้วยเสมอ ทั้งนี้ก็เพื่อรักษาให้ hashCode() ของคลาสที่เราเขียนขึ้นนั้นเป็นไปตาม general contract หรือข้อตกลงของ hashCode() ที่ถูกกำหนดไว้ว่า object ที่เท่ากัน จะต้องมีค่าของ hash code ที่เท่ากันด้วย (แต่ object ที่ไม่เท่ากันไม่จำเป็นต้องมีค่าของ hash code ที่เหมือนกัน) นอกจากนี้การ override hashCode() อย่างถูกต้อง จะทำให้เราสามารถใช้งาน object ของคลาสที่เราเขียนกับคลาสที่มีการใช้ค่า hash code ในการทำงาน อย่างเช่น HashTable, HashMap และ HashSet ได้อย่างถูกต้อง รายละเอียดการ override hashCode() สามารถอ่านได้จากบทความ "วิธีการ override hashCode() อย่างง่าย"

Example

public class Employee {
   private String _name;  // ชื่อ
   private int _age;  // อายุ
   private double _salary;   // เงินเดือน
   
   public Employee(String name, int age, double salary) {
      _name = name;
      _age = age;
      _salary = salary;
   }
  public boolean equals(Object o) {  // (1) เพิ่ม method declaration เพื่อ override equals()
     if (!(o instanceof Employee))  // (2) ตรวจสอบว่าเป็น object ของคลาสที่เราเขียน
        return false;
      
     Employee e = (Employee) o;  // (3) cast object ที่รับมาให้เป็นชนิดของคลาสที่เราเขียน
     // (4) เปรียบเทียบค่าภายใน object แต่ล่ะค่าว่าเท่ากันหรือไม่
     return _name.equals(e._name) && _age == e._age && Double.doubleToLongBits(_salary) == 
Double.doubleToLongBits(e._salary);
  }
   public static void main(String[] args) {
        Employee e1 = new Employee("John", 20, 25000.0);
        Employee e2 = new Employee("John", 20, 25000.0);
 
        System.out.println("e1 equals e2 ? = " + e1.equals(e2));
   }
}

Comment



smilebig smileopen-mounthed smileconfused smilesad smileangry smiletonguequestionembarrassedsurprised smilewinkdouble winkcry

Tweet