Menu
CoddyTech
flag Ar iconالعربيةdown icon

equals() و hashCode()

جزء من قسم البرمجة كائنية التوجه في رحلة Java على Coddy. الدرس 42 من 87.

عند مقارنة الكائنات في Java، يتحقق العامل == مما إذا كان مرجعان يشيران إلى موقع الذاكرة نفسه. لمقارنة المحتوى الفعلي للكائنات، تحتاج إلى إعادة تعريف الطريقة equals().

public class Person {
    private String name;
    private int age;
    
    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (obj == null || getClass() != obj.getClass()) return false;
        Person person = (Person) obj;
        return age == person.age && name.equals(person.name);
    }
}

تتبع الطريقة equals() نمطًا قياسيًا: تحقّق أولًا مما إذا كان الكائن هو نفسه، ثم تحقّق من النوع، وأخيرًا قارن الحقول ذات الصلة.

كلما أعدت تعريف equals()، يجب عليك أيضًا إعادة تعريف hashCode(). هذا شرط تعاقدي في Java: يجب أن يكون للكائنات المتساوية رمز التجزئة نفسه. تعتمد المجموعات القائمة على التجزئة، مثل HashMap وHashSet، على هذه القاعدة لتعمل بشكل صحيح.

@Override
public int hashCode() {
    return Objects.hash(name, age);
}

تُنشئ الطريقة المساعدة Objects.hash() رمز تجزئة من الحقول نفسها المستخدمة في equals(). إذا كان لكائني Person الاسم والعمر نفسيهما، فسيُعتبران متساويين وسيُنتجان رمزي تجزئة متطابقين، مما يضمن سلوكًا متسقًا في المجموعات.

challenge icon

التحدي

سهل

لنبنِ نظامًا لسجلات الطلاب يطبّق مساواة الكائنات بشكل صحيح. ستنشئ فئة Student بحيث يُعَدّ طالبان متساويين إذا كان لهما رقم الطالب والاسم نفسيهما، بصرف النظر عمّا إذا كانا الكائن نفسه في الذاكرة.

ستنظّم الشيفرة في ملفين:

  • Student.java: أنشئ فئة تمثّل طالبًا بثلاثة حقول خاصة: studentId (String)، وname (String)، وgpa (double). أضف مُنشئًا لتهيئة جميع الحقول، وطرائق getter لكل حقل.

    أعِد تعريف الطريقة equals() بحيث يُعَدّ كائنان من فئة Student متساويين عندما يكون لهما studentId نفسه وname نفسه. اتّبع النمط المعتاد: تحقّق من تطابق المرجع، ثم تحقّق من null والنوع، وبعد ذلك قارن الحقول ذات الصلة.

    أعِد تعريف الطريقة hashCode() باستخدام Objects.hash() مع الحقول نفسها المستخدمة في equals(). تذكّر استيراد java.util.Objects في أعلى الملف.

  • Main.java: اجعل فئة Student تعمل من خلال مقارنة كائنات الطلاب. ستتلقى ستة مدخلات تمثّل طالبين: رقم الطالب الأول واسمه ومعدّله التراكمي، ثم رقم الطالب الثاني واسمه ومعدّله التراكمي.

    أنشئ كائني Student، ثم أجرِ ثلاث مقارنات واطبع النتائج:

    1. اطبع Same reference: متبوعًا بما إذا كان الطالب الأول مساويًا لنفسه (يجب أن تكون النتيجة دائمًا true)
    2. اطبع Content equality: متبوعًا بما إذا كان الطالب الأول مساويًا للطالب الثاني (استنادًا إلى تطبيقك للطريقة equals)
    3. اطبع Hash codes match: متبوعًا بما إذا كان لكلا الطالبين رمز hash نفسه

ستتلقى ستة مدخلات: رقم الطالب الأول (String)، واسم الطالب الأول (String)، والمعدّل التراكمي للطالب الأول (double)، ورقم الطالب الثاني (String)، واسم الطالب الثاني (String)، والمعدّل التراكمي للطالب الثاني (double).

لاحظ أنه عندما يكون لدى طالبين رقما طالب واسمان متطابقان، تُرجع كل من equals() القيمة true وتتطابق رموز hash الخاصة بهما. هذا هو العقد الذي يجب عليك الحفاظ عليه!

جرّب بنفسك

import java.util.Scanner;

class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        
        // اقرأ بيانات الطالب الأول
        String id1 = scanner.nextLine();
        String name1 = scanner.nextLine();
        double gpa1 = scanner.nextDouble();
        scanner.nextLine(); // استهلك محرف السطر الجديد
        
        // اقرأ بيانات الطالب الثاني
        String id2 = scanner.nextLine();
        String name2 = scanner.nextLine();
        double gpa2 = scanner.nextDouble();
        
        // TODO: أنشئ كائنين من Student باستخدام بيانات الإدخال
        
        // TODO: اطبع "Same reference: " متبوعًا بما إذا كان student1 يساوي نفسه
        
        // TODO: اطبع "Content equality: " متبوعًا بما إذا كان student1 يساوي student2
        
        // TODO: اطبع "Hash codes match: " متبوعًا بما إذا كان الطالبان يمتلكان رمز التجزئة نفسه
    }
}
quiz iconاختبر نفسك

يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.

جميع دروس البرمجة كائنية التوجه

تدرّب بنفسك: مترجم Java عبر الإنترنت