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

دالة clone()

جزء من قسم Object Oriented Programming في رحلة Java على Coddy — الدرس 43 من 87.

تنشئ الطريقة clone() نسخة من كائن. لاستخدامها، يجب أن تقوم فئتك بتنفيذ واجهة Cloneable وإعادة تعريف الطريقة clone() من فئة Object.

public class Person implements Cloneable {
    private String name;
    private int age;
    
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    
    @Override
    public Person clone() {
        try {
            return (Person) super.clone();
        } catch (CloneNotSupportedException e) {
            throw new RuntimeException(e);
        }
    }
}

الآن يمكنك إنشاء نسخ مستقلة من الكائنات:

Person original = new Person("Alice", 25);
Person copy = original.clone();
// copy هو كائن منفصل بنفس القيم

بشكل افتراضي، تقوم clone() بإجراء نسخ سطحي (shallow copy)، مما يعني أنها تنسخ القيم الأولية والمراجع. إذا كان الكائن الخاص بك يحتوي على كائنات أخرى كحقول، فسيشير كل من الكائن الأصلي والنسخة إلى نفس الكائنات المتداخلة. للحصول على نسخ مستقلة تماماً مع كائنات متداخلة، تحتاج إلى تنفيذ نسخ عميق (deep copy) عن طريق استنساخ تلك الكائنات المتداخلة أيضاً داخل طريقة clone() الخاصة بك.

challenge icon

التحدي

سهل

لنقم ببناء نظام إدارة مستندات يوضح عملية استنساخ الكائنات (object cloning). ستقوم بإنشاء فئة Document يمكن استنساخها لإنشاء نسخ مستقلة، مما يسمح للمستخدمين بتكرار المستندات مع الحفاظ على المستند الأصلي كما هو.

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

  • Document.java: قم بإنشاء فئة تمثل مستنداً يدعم الاستنساخ. يحتوي المستند (Document) على ثلاثة حقول خاصة (private): title (String)، و author (String)، و version (int). قم بتضمين منشئ (constructor) لتهيئة جميع الحقول وطرق جلب (getter methods) لكل منها. أضف أيضاً طريقة setVersion(int version) لتحديث رقم الإصدار.

    اجعل فئة Document الخاصة بك تنفذ واجهة Cloneable وقم بإعادة تعريف (override) طريقة clone() لإرجاع Document. قم بمعالجة CloneNotSupportedException داخل الطريقة عن طريق تغليفها في RuntimeException.

    قم بإعادة تعريف toString() لإرجاع: Document[title=X, author=Y, version=Z] حيث X و Y و Z هي قيم الحقول الفعلية.

  • Main.java: قم بتفعيل فئة Document الخاصة بك عن طريق إنشاء مستند واستنساخه. ستتلقى ثلاثة مدخلات: العنوان (String)، والمؤلف (String)، ورقم الإصدار (int).

    قم بإنشاء مستند أصلي بهذه القيم، ثم استنسخه لإنشاء نسخة. بعد الاستنساخ، قم بتعديل إصدار النسخة عن طريق زيادته بمقدار 1 باستخدام setVersion(). يوضح هذا أن النسخة المستنسخة مستقلة تماماً عن الأصل.

    اطبع ثلاثة أسطر:

    1. Original: متبوعاً بـ toString() للمستند الأصلي
    2. Clone: متبوعاً بـ toString() للمستند المستنسخ
    3. Independent: متبوعاً بـ true أو false للإشارة إلى ما إذا كان الأصل والنسخة كائنين مختلفين (استخدم مقارنة !=)

ستتلقى ثلاثة مدخلات: عنوان المستند (String)، واسم المؤلف (String)، ورقم الإصدار (int).

لاحظ كيف أنه بعد تعديل إصدار النسخة المستنسخة، يظل المستند الأصلي دون تغيير - وهذا يثبت أن clone() أنشأت نسخة مستقلة حقاً!

ورقة مرجعية

تنشئ الطريقة clone() نسخة من كائن ما. لاستخدامها، يجب أن تنفذ فئتك واجهة Cloneable وتقوم بإعادة تعريف الطريقة clone() من فئة Object:

public class Person implements Cloneable {
    private String name;
    private int age;
    
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    
    @Override
    public Person clone() {
        try {
            return (Person) super.clone();
        } catch (CloneNotSupportedException e) {
            throw new RuntimeException(e);
        }
    }
}

إنشاء نسخ مستقلة:

Person original = new Person("Alice", 25);
Person copy = original.clone();
// copy هو كائن منفصل بنفس القيم

بشكل افتراضي، تقوم clone() بإجراء نسخ سطحي (shallow copy)، حيث تنسخ القيم الأولية والمراجع. إذا كان كائنك يحتوي على كائنات أخرى كحقول، فسيشير كل من الأصل والنسخة إلى نفس الكائنات المتداخلة. للحصول على نسخ مستقلة حقاً مع الكائنات المتداخلة، قم بتنفيذ نسخ عميق (deep copy) عن طريق استنساخ تلك الكائنات المتداخلة أيضاً داخل طريقة clone() الخاصة بك.

جرّب بنفسك

import java.util.Scanner;

class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        
        // قراءة المدخلات
        String title = scanner.nextLine();
        String author = scanner.nextLine();
        int version = scanner.nextInt();
        
        // TODO: إنشاء مستند أصلي (Document) بالقيم المدخلة
        
        // TODO: استنساخ المستند الأصلي لإنشاء نسخة
        
        // TODO: تعديل إصدار النسخة المستنسخة بزيادته بمقدار 1
        
        // TODO: طباعة "Original: " متبوعاً بالمستند الأصلي
        
        // TODO: طباعة "Clone: " متبوعاً بالمستند المستنسخ
        
        // TODO: طباعة "Independent: " متبوعاً بـ true/false (التحقق مما إذا كان الأصل != النسخة)
        
    }
}
quiz iconاختبر نفسك

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

جميع دروس Object Oriented Programming