این مطلب براساس زبان جاوا نوشته شده اما احتمالا اشتراکاتی با زبانی که شما کارمیکنید هم دارد.
موضوع آنقدر پیچیده نیست اما ممکن است اگر دو مفهوم اصلی را ندونید کمی گیچ کننده باشد.
مسئله سادست ما آبجکتی مثل زیر داریم :
Person a=new Person(); a.name="parsa" a.age="22"
(کلاس person هیچ چیز جز همین دوتا فیلد نداره و برای سادگی از getter و setter استفاده نشده). حالا میخواهیم از این آبجکت کپی بگیریم. اولین راهی که به ذهن ما میرسد ساختن یک متغیر دیگر و مساوی قرار دادنش با متغیر a است به این شکل :
Person b= a;
به این روش کپی shallow copy میگونید یعنی کپی کمعمق. در این روش کپی انجام میشود اما مشکل اینجاست که اگر با مفهوم Reference آشنا باشید میدونید که متغیر a حاوی خود آبجکت نیست بلکه حاوی اشارهگریایست که به آبجکت a اشاره میکند. و الان اون اشارهگر رو ریخته تو b بنابراین اگر بگیم :
b.name= "Ali"
آبجکت a هم فیلد اسمش برابر با ali میشه که در اکثر موارد ما نمیخوایم اینجوری بشه . برای این که اینجوری نشه باید بیایم دونه دونه ویژگیهای آبجکت a رو برابر با آبجکت b قرار بدیم :
b.name = a.name; b.age = a.age`
به این روش که دیگه مشکل قبلیو نداره و دوتا آبجکت با مقادیر مساوی اما سوای از هم میسازه deep copy میگن که اکثر ما به این نیاز داریم.
خب خیلی وقتا کلاس ما به سادگی کلاس Person نیست و کپی کردنش ممکنه حوصله سربر و دردسرساز باشه. برای همین توی جاوا میشه از فیچر cloneAble استفاده کرد.
یکم فیچر گیج کنندهایه پس به این بخش حرفم خوب توجه کنید :
در کلاس Object که والد همه کلاسها در جاوا هست و همه متدهای اونو ارث میبرند متدی وجود داره به اسم clone که میشه باهاشم آبجکتتون رو کپی کنید اونم به روش deep اما نکته اینه که این متد protect است. بنابراین باید اونو داخل کلاس خودتون در یک متد صدا بزنید و پس از اون از بیرون کلاس قابل استفادس. مثال تو همین کلاس Person :
public class Person { public Person clone() throws CloneNotSupportedException{ return (Person) super.clone(); } }
خب اون cast بخاطر اینه که clone داخل کلاس Object مقدار برگشتیش همون Object است.
حالا میتونید این متد رو از بیرون کلاس صدا بزنید :
try{ Person b = a.clone(); }catch(CloneNotSupportedException e){ // Handle exp }
اما این کد خطا خواهد داشت !!!
متد clone یک متد امنیتی محسوب میشه و شما صراحتا باید به کلاستون اجازه این کار رو بدید. اون اکسپشن هم دقیقا برای همینه که اگه کلاس شما اجازه اینکار رو نداشت پرتاب (throw) بشه و اجازه ادامه نده.
اما چگونه دسترسی رو بدیم؟
کافیه اینترفیس Cloneable رو implement کنیم این واسط یک marker هست و هیچ متدی واسه پیاده سازی نداره و تنها به JVM میگه که این کلاس میتونه super.clone رو صدا بزنه
public class Person implements Cloneable{ public Person clone() throws CloneNotSupportedException{ return (Person) super.clone(); } }
حالا شما میتونید آبجکت خودتونو براحتی clone کنید. در پست بعدی به بدیهای روش clone اشاره میکنم و پیشنهاد جایگزین خودم رو بهتون میدم.
مرسی که وقت گذاشتید امیدوارم تونسته باشم کمکتون کنم. خوشحال میشم توی صفحه توئیترم بیشتر باهم معاشرت کنیم.