Menu
Coddy logo textTech
flag Ar iconالعربيةdown icon

equals() و hashCode()

جزء من قسم Object Oriented Programming في رحلة 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: الكائنات المتساوية يجب أن تمتلك نفس الـ hash code. المجموعات القائمة على التجزئة مثل HashMap و HashSet تعتمد على هذه القاعدة لتعمل بشكل صحيح.

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

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

challenge icon

التحدي

سهل

لنقم ببناء نظام سجلات طلاب يقوم بتنفيذ مساواة الكائنات (object equality) بشكل صحيح. ستقوم بإنشاء فئة Student حيث يُعتبر الطالبان متساويين إذا كان لهما نفس معرف الطالب والاسم — بغض النظر عما إذا كانا نفس الكائن في الذاكرة أم لا.

ستقوم بتنظيم الكود الخاص بك عبر ملفين:

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

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

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

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

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

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

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

لاحظ كيف أنه عندما يتطابق معرفا الطالبين واسماهما، فإن equals() تعيد true وَ تتطابق رموز التجزئة الخاصة بهما — هذا هو العقد (contract) الذي يجب عليك الحفاظ عليه!

جرّب بنفسك

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: " متبوعة بما إذا كان لكلا الطالبين نفس الـ hash code
    }
}
quiz iconاختبر نفسك

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

جميع دروس Object Oriented Programming