การ Shallow Copy เป็นการสร้าง object ใหม่ แล้วคัดลอก field ที่เป็น value type (เช่น int, float, bool) จาก original object ไป object ใหม่และ ข้อมูลใน filed ของทั้งสอง object จะถูกเก็บไว้คนละตำแหน่งหน่วยความจำ แต่ถ้า field เป็น reference type (เช่น array, object, string) จะคัดลอกเฉพาะ reference ของ field เท่านั้น ทำให้ข้อมูลใน field นั้นของ object ทั้งสองชี้ไปที่ตำแหน่งหน่วยความจำเดียวกัน ซึ่งการที่ field ทั้งสองชี้ไปที่ตำแหน่งหน่วยความจำเดียวกัน ทำให้ถ้าข้อมูลของ field ใน object ใด object หนึ่งเปลี่ยน ข้อมูลใน field นั้นของอีก object ก็จะเปลี่ยนตาม จึงเกิดปัญหาเวลาต้องการเปลี่ยนค่าใน field ของ object เดียวแต่ ไม่อยากให้อีก object เปลี่ยนด้วย shallow Copy จึงเหมาะกับการใช้งานกับ object ที่มี field ที่เป็น value type หรือ คัดลอกไปแต่ไม่ได้เปลี่ยนค่าใน field ที่เป็น reference type
ตัวอย่างการ Shallow Copy
ในภาพนี้ได้ทำการ Shallow Copy สร้าง object G2 ขึ้นมาใหม่ แล้วคัดลอก field Global rank ที่เป็น value type จาก object G1 ไป object G2 คือ 548(int) และถูกเก็บไว้ในคนละตำแหน่งหน่วยความจำกับ object G1 แต่ field Desc ที่เป็น reference type (string) คัดลอกเฉพาะ reference ของ field Desc ซึ่งถูกเก็บไว้ในตำแหน่งหน่วยความจำเดียวกันกับ object G1
using System;
class Example
{
public static void Main(string[] args)
{
Company G1 = new Company(548, "GeeksForGeeks");
Company G2 = (Company)G1.Shallowcopy();
Console.WriteLine("ก่อนเปลี่ยนค่าของ field Global rank กับ Desc : ");
Console.WriteLine(G1.GlobalRank);
Console.WriteLine(G2.GlobalRank);
Console.WriteLine(G2.desc.CompanyName);
Console.WriteLine(G1.desc.CompanyName);
G2.GlobalRank = 59;
G2.desc.CompanyName = "GFG";
Console.WriteLine("หลังเปลี่ยนค่าของ field Global rank กับ Desc : ");
Console.WriteLine(G1.GlobalRank);
Console.WriteLine(G2.GlobalRank);
Console.WriteLine(G2.desc.CompanyName);
Console.WriteLine(G1.desc.CompanyName);
}
}
class Company
{
public int GlobalRank;
public CompanyDescription desc;
public Company(int gbRank, string c)
{
GlobalRank = gbRank;
desc = new CompanyDescription(c);
}
public object Shallowcopy()
{
return this.MemberwiseClone();
}
}
class CompanyDescription
{
public string CompanyName;
public CompanyDescription(string c)
{
CompanyName = c;
}
}
class CompanyDescription {
public String CompanyName;
public CompanyDescription(String c) {
this.CompanyName = c;
}
}
class Company implements Cloneable {
public int GlobalRank;
public CompanyDescription desc;
public Company(int gbRank, String c) {
this.GlobalRank = gbRank;
this.desc = new CompanyDescription(c);
}
public Object shallowCopy() throws CloneNotSupportedException {
return super.clone();
}
}
public class Example {
public static void main(String[] args) {
try {
Company G1 = new Company(548, "GeeksforGeeks");
Company G2 = (Company) G1.shallowCopy();
System.out.println("ก่อนที่จะแก้ไขค่า field Global rank กับ Desc : ");
System.out.println(G1.GlobalRank);
System.out.println(G2.GlobalRank);
System.out.println(G1.desc.CompanyName);
System.out.println(G2.desc.CompanyName);
G1.GlobalRank = 59;
G2.desc.CompanyName = "GFG";
System.out.println("หลังจากที่จะแก้ไขค่า field Global rank กับ Desc : ");
System.out.println(G1.GlobalRank);
System.out.println(G2.GlobalRank);
System.out.println(G1.desc.CompanyName);
System.out.println(G2.desc.CompanyName);
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
}
}
import copy
class CompanyDescription:
def __init__(self, c):
self.CompanyName = c
class Company:
def __init__(self, gbRank, c):
self.GlobalRank = gbRank
self.desc = CompanyDescription(c)
def shallow_copy(self):
return copy.copy(self)
if __name__ == "__main__":
G1 = Company(548, "GeeksforGeeks")
G2 = G1.shallow_copy()
print("ก่อนเปลี่ยนค่าของ field Global rank กับ Desc : ")
print(G1.GlobalRank)
print(G2.GlobalRank)
print(G1.desc.CompanyName)
print(G2.desc.CompanyName)
G1.GlobalRank = 59
G2.desc.CompanyName = "GFG"
print("หลังเปลี่ยนค่าของ field Global rank กับ Desc : ")
print(G1.GlobalRank)
print(G2.GlobalRank)
print(G1.desc.CompanyName)
print(G2.desc.CompanyName)
Output
ก่อนเปลี่ยนค่าของ field Global rank กับ Desc :
548
548
GeeksforGeeks
GeeksforGeeks
หลังเปลี่ยนค่าของ field Global rank กับ Desc :
548
59
GFG
GFG
Deep Copy คืออะไร?
การ Deep Copy เป็นการสร้าง object ใหม่ แล้วคัดลอก field ทั้ง value type และ reference type ไปไว้คนละตำแหน่งหน่วยความจำของ original object ในการใช้งานถ้าเราไม่ได้ต้องการเปลี่ยนค่าใน field ที่เป็น reference type ของ object ก็ไม่จำเป็นต้องใช้วิธี Deep Copy เนื่องจากซับซ้อนกว่าการใช้ Shallow Copy
ตัวอย่างการ Deep Copy
ในภาพนี้ได้ทำการ Deep Copy สร้าง object G2 ขึ้นมาใหม่ แล้วคัดลอก field Global rank ที่เป็น value type จาก object G1 ไป object G2 คือ 548( int ) และเก็บไว้คนละตำแหน่งหน่วยความจำกับ object G1 ในส่วนของ field Desc ที่เป็น reference type( string ) Desc ของ object G1 และ object G2 คือ GeeksforGeeks( string ) และเก็บข้อมูลไว้คนละตำแหน่งหน่วยความจำกับ object G1
เปรียบการ Deep Copy ในภาษาต่างๆ
C++
ใน C++ การ Deep Copy เป็นการคัดลอกที่ object ใหม่จะถูกสร้างโดยการคัดลอกข้อมูลของตัวแปรทั้งหมดจาก original object ไปยัง object ใหม่ และมีการ allocate memory ที่ใกล้เคียงกัน(ไม่ใช่ตำแหน่งเดียวกัน)ให้ object ใหม่ แต่มีค่าเดียวกัน
Java
ใน java class ที่เราต้องการทำ Deep Copy จะต้อง implement interface Cloneable เพื่อกำหนดว่า class นี้คัดลอกได้ ต้อง override method Clone() ของ class object เพื่อกำหนด method ที่เราต้องการให้คัดลอก objectในและ เมธอด clone() จะต้องมีทำการสร้าง object ใหม่ และคัดลอกค่าของข้อมูลจาก original object ไปยัง object ใหม่ทั้งหมด
Python
ใน Python การ Deep Copy เป็นการคัดลอกที่จะมีการสร้าง object ใหม่ขึ้นมาก่อน ซึ่งตำแหน่งหน่วยความจำต่างจาก original object แล้วคัดลอกข้อมูลจาก original object ไปที่ object ใหม่
ตัวอย่างโค้ดการ Deep Copy
using System;
class Example {
public static void Main(string[] args)
{
Company G1 = new(548, "GeeksforGeeks");
Company G2 = (Company)G1.DeepCopy();
Console.WriteLine("ก่อนเปลี่ยนค่าของ field Global rank กับ Desc : ");
Console.WriteLine(G1.GlobalRank);
Console.WriteLine(G2.GlobalRank);
Console.WriteLine(G1.desc.CompanyName);
Console.WriteLine(G2.desc.CompanyName);
G2.GlobalRank = 59;
G2.desc.CompanyName = "GFG";
Console.WriteLine("\nหลังเปลี่ยนค่าของ field Global rank กับ Desc : ");
Console.WriteLine(G1.GlobalRank);
Console.WriteLine(G2.GlobalRank);
Console.WriteLine(G1.desc.CompanyName);
Console.WriteLine(G2.desc.CompanyName);
}
}
class Company {
public int GlobalRank;
public CompanyDescription desc;
public Company(int gbRank, string c)
{
this.GlobalRank = gbRank;
this.desc = new CompanyDescription(c);
}
public Company DeepCopy() {
return new Company(this.GlobalRank, this.desc.CompanyName);
}
}
class CompanyDescription {
public string CompanyName;
public CompanyDescription(string c) {
this.CompanyName = c;
}
}
#include <iostream>
#include <string>
using namespace std;
class CompanyDescription {
public:
string CompanyName;
CompanyDescription(string c) : CompanyName(c) {}
};
class Company {
public:
int GlobalRank;
CompanyDescription* desc;
Company(int gbRank, string c) : GlobalRank(gbRank) {
desc = new CompanyDescription(c);
}
Company* DeepCopy() {
return new Company(this->GlobalRank, this->desc->CompanyName);
}
~Company() {
delete desc;
}
};
int main() {
Company* G1 = new Company(548, "GeeksforGeeks");
Company* G2 = G1->DeepCopy();
cout << "ก่อนแก้ไขค่า field Global rank กับ Desc : " << endl;
cout << G1->GlobalRank << endl;
cout << G1->desc->CompanyName << endl;
cout << G2->GlobalRank << endl;
cout << G2->desc->CompanyName << endl;
G2->GlobalRank = 59;
G2->desc->CompanyName = "GFG";
cout << "หลังแก้ไขค่า field Global rank กับ Desc : " << endl;
cout << G1->GlobalRank << endl;
cout << G1->desc->CompanyName << endl;
cout << G2->GlobalRank << endl;
cout << G2->desc->CompanyName << endl;
delete G1;
delete G2;
return 0;
}
class CompanyDescription {
public String CompanyName;
public CompanyDescription(String c) {
this.CompanyName = c;
}
}
class Company {
public int GlobalRank;
public CompanyDescription desc;
public Company(int gbRank, String c) {
this.GlobalRank = gbRank;
this.desc = new CompanyDescription(c);
}
public Company DeepCopy() {
return new Company(this.GlobalRank, this.desc.CompanyName);
}
}
public class Example {
public static void main(String[] args) {
Company G1 = new Company(548, "GeeksforGeeks");
Company G2 = G1.DeepCopy();
System.out.println("ก่อนแก้ไขค่าของ field Global rank กับ Desc : ");
System.out.println(G1.GlobalRank);
System.out.println(G1.desc.CompanyName);
System.out.println(G2.GlobalRank);
System.out.println(G2.desc.CompanyName);
G2.GlobalRank = 59;
G2.desc.CompanyName = "GFG";
System.out.println("หลังแก้ไขค่าของ field Global rank กับ Desc : ");
System.out.println(G1.GlobalRank);
System.out.println(G1.desc.CompanyName);
System.out.println(G2.GlobalRank);
System.out.println(G2.desc.CompanyName);
}
}
class CompanyDescription:
def __init__(self, c):
self.CompanyName = c
class Company:
def __init__(self, gbRank, c):
self.GlobalRank = gbRank
self.desc = CompanyDescription(c)
def DeepCopy(self):
return Company(self.GlobalRank, self.desc.CompanyName)
if __name__ == "__main__":
G1 = Company(548, "GeeksforGeeks")
G2 = G1.DeepCopy()
print("ก่อนแก้ไขค่าของ field Global rank กับ Desc : ")
print(G1.GlobalRank)
print(G1.desc.CompanyName)
print(G2.GlobalRank)
print(G2.desc.CompanyName)
G2.GlobalRank = 59
G2.desc.CompanyName = "GFG"
print("หลังแก้ไขค่าของ field Global rank กับ Desc : ")
print(G1.GlobalRank)
print(G1.desc.CompanyName)
print(G2.GlobalRank)
print(G2.desc.CompanyName)
Output
ก่อนเปลี่ยนค่าของ field Global rank กับ Desc :
548
548
GeeksforGeeks
GeeksforGeeks
หลังเปลี่ยนค่าของ field Global rank กับ Desc :
548
59
GFG
GeeksforGeeks