الفريق العربي للبرمجةأرشيف المنتديات · 2000 – 2023
نسخة أرشيفية للقراءة فقط — التسجيل والمشاركة مغلقان، والمحتوى محفوظ كما كان.

آلية نسخ الكائنات

بدأه sameh mahmoud في 29 مارس 2010 · 16 رد · 1,970 مشاهدة · في JavaSE
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

كيف اعمل نسخة جديدة من الكائن ؟؟

بحيث لا تتغير اى خاصية من خواص احدهما بتغير الاخرى .

سبـــــحــــان الله و بحمده سبحان الله العظيم

403100468.gif

#2

هناك ثلاثة أنواع من النسخ:

النسخ الضحل shallow copy: وهذا النوع من النسخ يقوم بنسخ المؤشر reference فقط بمعنى آخر يصبح لدينا كائن واحد ومؤشرين

يقدم لنا سرعة عالية لكنه لا يضمن لنا نسخة من الكائن لكل مؤشر

النسخ العميق Deep copy: وهذا النوع يعمل على نسخ الكائن نفسه بمعنى آخر يصبح لدينا كائنين ومؤشرين

صحيح أنه بطيء لأنه يأخذ وقت في إنشاء كائن جديد لكنه يضمن لنا نسختين مختلفتين تماماً

النسخ المتأخر lazy copy: وهذا النوع يقوم بالجمع بين النوعين السابقين

بحيث يقوم مبدئياً بعمل reference جديد

في حال أردنا التغيير على الكائن هنا يفكر في إنشاء كائن جديد

حدد ما النوع الذي تريده بالضبط وسأدلك على آلية البناء في جافا

سأفصل هذا السؤال في موضوع جديد

تحياتي

حزمة المحرك الإصدارة 0.8

أي أحد يجد أني ظلمته فليراسلني

وبإذن الله لو كان له حق سيأخذه

728x90.png

#3

شكرا يا شيخ علاء على المتابعة

اليك المطلوب :

اولا انظر الفئة التالية و هي sameh

package copysameh;

public class sameh {
    private int SamehSize;
    public sameh()
    {
        SamehSize = 5000;
    }
    public void setSamehSize(int Hight)
    {
        this.SamehSize = Hight;
    }
    public int getSamehSize()
    {
        return this.SamehSize;
    }
}

الكلاس Main

public class Main {


    public static void main(String[] args) {
        sameh s = new sameh();
        sameh s2 = s;
        s.setSamehSize(400);
        s2.setSamehSize(600);
        System.out.println(s.getSamehSize()); // من المتوقع طباعة 400 و لكن يتم طباعة 600 !!
    }
}

كما رأيت يتم طباعة 600 رغم اننا وضعنا المتغير SamehSize في الكائن s بـ 400

اعتقد ان الحل هو في Deep Copy هل صحيح ؟؟

سبـــــحــــان الله و بحمده سبحان الله العظيم

403100468.gif

#4

s و s1 هما 2 references لكنهما يشيران إلى نفس الكائن في الذاكرة، وبالتالي فكل تغيير تطبقه على s سينطبق أيضا على s1

إستعمل ال method clone الموروثة من Object، واعمل implement لل interface Cloneable

public class Sameh implements Cloneable {

	private int SamehSize;

	public Sameh()
	{
		SamehSize = 5000;
	}
	public void setSamehSize(int Hight)
	{
		this.SamehSize = Hight;
	}
	public int getSamehSize()
	{
		return this.SamehSize;
	}
	public static void main(String[] args) throws CloneNotSupportedException {
		Sameh s = new Sameh();
		Sameh s2 = (Sameh)s.clone();
		s.setSamehSize(400);
		s2.setSamehSize(600);
		System.out.println(s.getSamehSize());	//print 400
		System.out.println(s2.getSamehSize());	//print 600
	}
}

أو اكتب copy constructor داخل ال class

public class Sameh {

	//........
	public Sameh(Sameh s) {
		SamehSize = s.getSamehSize();
	}
	//........
	public static void main(String[] args) {
		Sameh s = new Sameh();
		Sameh s2 = new Sameh(s);
		//..........
	}
}
#5
اقتباس
public class Main {


    public static void main(String[] args) {
        sameh s = new sameh();
        sameh s2 = s;
        s.setSamehSize(400);
        s2.setSamehSize(600);
        System.out.println(s.getSamehSize()); // من المتوقع طباعة 400 و لكن يتم طباعة 600 !!
    }
}

هذا ليس أي نوع من النسخ,,,,,

يجب عليك إستخدام الداله clone من الواجهه Clonable

#6
JustPassing كتب:

s و s1 هما 2 references لكنهما يشيران إلى نفس الكائن في الذاكرة، وبالتالي فكل تغيير تطبقه على s سينطبق أيضا على s1

إستعمل ال method clone الموروثة من Object، واعمل implement لل interface Cloneable

public class Sameh implements Cloneable {

	private int SamehSize;

	public Sameh()
	{
		SamehSize = 5000;
	}
	public void setSamehSize(int Hight)
	{
		this.SamehSize = Hight;
	}
	public int getSamehSize()
	{
		return this.SamehSize;
	}
	public static void main(String[] args) throws CloneNotSupportedException {
		Sameh s = new Sameh();
		Sameh s2 = (Sameh)s.clone();
		s.setSamehSize(400);
		s2.setSamehSize(600);
		System.out.println(s.getSamehSize());	//print 400
		System.out.println(s2.getSamehSize());	//print 600
	}
}

أو اكتب copy constructor داخل ال class

public class Sameh {

	//........
	public Sameh(Sameh s) {
		SamehSize = s.getSamehSize();
	}
	//........
	public static void main(String[] args) {
		Sameh s = new Sameh();
		Sameh s2 = new Sameh(s);
		//..........
	}
}

شكرا لك اخي الكريم و لكن الطريقة clone هيا protected !

سبـــــحــــان الله و بحمده سبحان الله العظيم

403100468.gif

#7
sameh mahmoud كتب:

شكرا لك اخي الكريم و لكن الطريقة clone هيا protected !

وكل class يتم إنشائها ترث تلقائيا من Object، فأين المشكل؟؟

#8
JustPassing كتب:

وكل class يتم إنشائها ترث تلقائيا من Object، فأين المشكل؟؟

لا استطيع استدعائها كما اشرت لي هنا

Sameh s2 = (Sameh)s.clone();

سبـــــحــــان الله و بحمده سبحان الله العظيم

403100468.gif

#10

يجب أن تستخدم الواجهة cloneable

ثم تقوم بعمل override للدالة clone

بحيث تقوم بإنشاء كائن جديد بمدخلات نفس الكائن القديم إذا كنت تريد أن تقوم بعمل نسخة ضحلة shallow

إما إذا كنت تريد عمل نسخة عميقة deep فتحتاج إلى تكرار الموضوع مع كل الكائنات التي ترتبطها علاقة بالكائن الحالي

تحياتي

حزمة المحرك الإصدارة 0.8

أي أحد يجد أني ظلمته فليراسلني

وبإذن الله لو كان له حق سيأخذه

728x90.png

#11

يجب توضيح امر مهم بعض الشيء في الرابط الذي وضعته مسبقا http://en.wikipedia.org/wiki/Object_copy#Copying_in_Java

اقتباس

Another way to copy objects in Java is to serialize them through the Serializable interface. This is typically used for persistence and wire protocol purposes, but it does create copies of objects and, unlike clone, a deep copy that gracefully handles cycled graphs of objects is readily available with minimal effort from the programmer.

Both of these methods suffer from a notable problem: the constructor is not used for objects copied with clone or serialization. This can lead to bugs with improperly initialized data, prevents the use of final member fields, and makes maintenance challenging.

ان الConstructor لا يتم استخدامه او استدعائه في كلا الحالتين من النسخ للكائن (Clone or Serialization)

والذي قد يؤدي لعدم اعطاء قيم اولية للمتغيرات و هذا قد يحد من استخدام النتغيرات النهائية (final)

و قد يكون فيه تحدي لصيانة البرنامج او الكود

#12

هذا مثال بسيط على عملية النسخ

package clone;

public class CloneTest implements Cloneable {
	private final String a;

	public CloneTest(String a) {
		this.a = a;
	}

	public static void main(String[] args) {
		try {
			CloneTest test = new CloneTest(new String("alaa"));
			CloneTest test2 = (CloneTest) test.clone();
			System.out.println(test+" "+test2);
			System.out.println(test2.a==test.a);
		} catch (CloneNotSupportedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

في هذا المثال لم أقم بتغيير بإعادة كتابة الدالة clone نلاحظ أني حصلت على نسخة ضحلة shallow

لأن الجملة التالية test2.a==test.a تعطي جواباً صحيحاً

لو أردت أن أحصل على نسخة عميقة deep

فعلي أن أقوم بإعادة كتابة الدالة clone

تحياتي

حزمة المحرك الإصدارة 0.8

أي أحد يجد أني ظلمته فليراسلني

وبإذن الله لو كان له حق سيأخذه

728x90.png

#13

بالمناسبة بعد النقاش الرائع الذي دار هنا

قمت بإضافة الموضوع إلى المواضيع المميزة تحت قسم البرمجة الكائنية

تحياتي

حزمة المحرك الإصدارة 0.8

أي أحد يجد أني ظلمته فليراسلني

وبإذن الله لو كان له حق سيأخذه

728x90.png

#14
علاء الصالحي كتب:

هذا مثال بسيط على عملية النسخ

package clone;

public class CloneTest implements Cloneable {
	private final String a;

	public CloneTest(String a) {
		this.a = a;
	}

	public static void main(String[] args) {
		try {
			CloneTest test = new CloneTest(new String("alaa"));
			CloneTest test2 = (CloneTest) test.clone();
			System.out.println(test+" "+test2);
			System.out.println(test2.a==test.a);
		} catch (CloneNotSupportedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

تحياتي

أخ علاء ممكن تشرح مقصدك او لو حتى بمثال آخر لانه تشابكت عندي الامور

ما أقصده هو ما كنت تعنيه هنا

علاء الصالحي كتب:

في هذا المثال لم أقم بتغيير بإعادة كتابة الدالة clone نلاحظ أني حصلت على نسخة ضحلة shallow

لأن الجملة التالية test2.a==test.a تعطي جواباً صحيحاً

لو أردت أن أحصل على نسخة عميقة deep

فعلي أن أقوم بإعادة كتابة الدالة clone

تحياتي

وشكرا

تم تعديل هذه المشاركة بواسطة vector_ever في 11 مارس 2011 في 04:13

إذا نظــرتَ نيـوب اللـّيـثِ بـارزةً         فـلا تظــنَنَ أَنَّ اللـّيـــثَ يبْتسـِـــمُ


 


 


رسم المخططات البيانية بواسطة الجافا


 


كتاب تحليل وتصميم نظم المعلومات


#15

المثال هنا يقول التالي

عملية الاستنساخ clone الموجودة أصلاً في الفئة Object

تقوم فقط بعمل نسخة جديدة من الكائن المستنسخ لكنها لا تقوم بعمل نسخة جديدة من الكائنات الأعضاء لهذا الكائن

لاحظ أنه لو كان الكلام صحيح فإنه يفترض بجملة الطباعة أن تعيد false

لكن وبما أن عملية الاستنساخ لا تتم بعمق فالجملة تعيد true

تحياتي

حزمة المحرك الإصدارة 0.8

أي أحد يجد أني ظلمته فليراسلني

وبإذن الله لو كان له حق سيأخذه

728x90.png

#16

اعذرني اخي مرة ثانية ما قصدته انني لم افهم هذه المقولة بالتحديد

علاء الصالحي كتب:

في هذا المثال لم أقم بتغيير بإعادة كتابة الدالة clone نلاحظ أني حصلت على نسخة ضحلة shallow

لأن الجملة التالية test2.a==test.a تعطي جواباً صحيحاً

لو أردت أن أحصل على نسخة عميقة deep

فعلي أن أقوم بإعادة كتابة الدالة clone

أعني اننا قمنا بعملية نسخ clone والمفروض وقتها ان يكون النسخ عميق اي ان يتكون لدي كائن جديد لا يتاثر بالكائن المنسوخ منه

فكيف هنا تقول لو انك اردت أن تحصل على نسخة عميقة deep

فعليك أن تقوم بإعادة كتابة الدالة clone

اولم نفعل ذلك مسبقا ؟؟؟

إذا نظــرتَ نيـوب اللـّيـثِ بـارزةً         فـلا تظــنَنَ أَنَّ اللـّيـــثَ يبْتسـِـــمُ


 


 


رسم المخططات البيانية بواسطة الجافا


 


كتاب تحليل وتصميم نظم المعلومات


#17

بمعنى أنه يجب عليك أن تقوم بإعادة كتابة الدالة clone

public Object clone(){
//writing some code here to doing clone
}

لم أقم بذلك من قبل لذا قم بعمل بحث عن الموضوع

تحياتي

حزمة المحرك الإصدارة 0.8

أي أحد يجد أني ظلمته فليراسلني

وبإذن الله لو كان له حق سيأخذه

728x90.png

مواضيع مشابهة