@@ -3,11 +3,48 @@ package com.baeldung.cloningobject
3
3
import org.assertj.core.api.Assertions.assertThat
4
4
import org.junit.jupiter.api.Test
5
5
6
+ /* **
7
+ Class Scheme
8
+ ============================
9
+
10
+ Address
11
+ ├── street: String
12
+ └── city: String
13
+
14
+ Person
15
+ ├── name: String
16
+ └── address: Address
17
+
18
+ Organization
19
+ ├── name: String
20
+ ├── headquarters: Address
21
+ └── companies: List<Company>
22
+ └── Company
23
+ ├── name: String
24
+ ├── industry: String
25
+ ├── ceo: Person
26
+ │ ├── name: String
27
+ │ └── address: Address
28
+ └── employees: List<Person>
29
+ └── Person
30
+ ├── name: String
31
+ └── address: Address
32
+
33
+ data class Address(var street: String, var city: String)
34
+ data class Person(var name: String, var address: Address)
35
+ data class Company(var name: String, var industry: String, val ceo: Person, val employees: List<Person>)
36
+ data class Organization(var name: String, val headquarters: Address, val companies: List<Company>)
37
+ */
38
+
6
39
data class Address (var street : String , var city : String ) : Cloneable {
40
+
7
41
public override fun clone (): Address = super .clone() as Address
42
+
43
+ // constructor(address: Address) : this(address.street, address.city)
8
44
}
9
45
10
46
data class Person (var name : String , var address : Address ) : Cloneable {
47
+
11
48
public override fun clone () = Person (name, this .address.clone())
12
49
13
50
fun deepCopy (name : String = this.name, address : Address = this.address.copy()): Person {
@@ -18,101 +55,47 @@ data class Person(var name: String, var address: Address) : Cloneable {
18
55
}
19
56
20
57
data class Company (var name : String , var industry : String , val ceo : Person , val employees : List <Person >) : Cloneable {
58
+
59
+ fun deepCopy (name : String = this.name, industry : String = this.industry, ceo : Person = this.ceo.deepCopy(),
60
+ employees : List <Person > = this.employees.map { it.deepCopy() }): Company {
61
+ return Company (name, industry, ceo, employees)
62
+ }
63
+
21
64
public override fun clone (): Company {
22
65
return Company (name, industry, ceo.clone(), employees.map { it.clone() })
23
66
}
24
- }
25
67
26
- data class Organization (var name : String , val headquarters : Address , val companies : List <Company >) : Cloneable {
27
- public override fun clone (): Organization {
28
- return Organization (name, headquarters.clone(), companies.map { it.clone() })
29
- }
68
+ constructor (company: Company ) : this (company.name, company.industry, Person (company.ceo),
69
+ company.employees.map { Person (it) })
30
70
}
31
71
32
- class CloningObjectUnitTest {
33
-
34
- private val address = Address (" Jln. Kemasan" , " Yogyakarta" )
35
- private val person = Person (" Hangga Aji Sayekti" , address)
36
-
37
- @Test
38
- fun `when using secondary constructor then proves that shallow copy` () {
39
- val clonedPerson = Person (person)
40
- assertThat(clonedPerson).isNotSameAs(person)
41
-
42
- person.address.city = " Surabaya"
43
- person.address.street = " Jln. Ahmad Yani"
44
-
45
- assertThat(clonedPerson.address.city)
46
- .isNotEqualTo(" Surabaya" )
72
+ data class Organization (var name : String , val headquarters : Address , val companies : List <Company >) : Cloneable {
47
73
48
- assertThat(clonedPerson.address.street)
49
- .isNotEqualTo(" Jln. Ahmad Yani" )
74
+ fun deepCopy (name : String = this.name, headquarters : Address = this.headquarters.copy(),
75
+ companies : List <Company > = this.companies.map { it.deepCopy() }) : Organization {
76
+ return Organization (name, headquarters, companies)
50
77
}
51
78
52
- @Test
53
- fun `when using copy then proves that shallow copy or deep copy` () {
54
- val clonedPerson = person.copy()
55
- assertThat(clonedPerson).isNotSameAs(person)
56
-
57
- person.address.city = " Jakarta"
58
- person.address.street = " Jln. Abdul Muis"
59
-
60
- assertThat(clonedPerson.address.city)
61
- .isEqualTo(" Jakarta" )
62
-
63
- assertThat(clonedPerson.address.street)
64
- .isEqualTo(" Jln. Abdul Muis" )
65
-
66
- val deepClonedPerson = person.copy(address = address.copy())
67
- assertThat(deepClonedPerson).isNotSameAs(person)
68
-
69
- person.address.city = " Banda Aceh"
70
- person.address.street = " Jln. Cut Nyak Dhien"
71
-
72
- assertThat(deepClonedPerson.address.city)
73
- .isNotEqualTo(" Banda Aceh" )
74
-
75
- assertThat(deepClonedPerson.address.street)
76
- .isNotEqualTo(" Jln. Cut Nyak Dhien" )
79
+ public override fun clone (): Organization {
80
+ return Organization (name, headquarters.clone(), companies.map { it.clone() })
77
81
}
78
82
79
- @Test
80
- fun `when using clone then proves that shallow copy` () {
81
- val clonedPerson = person.clone()
82
- assertThat(clonedPerson).isNotSameAs(person)
83
-
84
- person.address.city = " Palembang"
85
- person.address.street = " Jln. Abi Hasan"
86
-
87
- assertThat(clonedPerson.address.city)
88
- .isNotEqualTo(" Palembang" )
83
+ constructor (organization: Organization ) : this (organization.name, organization.headquarters.copy(),
84
+ organization.companies.map { Company (it) })
85
+ }
89
86
90
- assertThat(clonedPerson.address.street)
91
- .isNotEqualTo(" Jln. Abi Hasan" )
92
- }
87
+ class CloningObjectUnitTest {
93
88
94
89
@Test
95
- fun `when own function then proves that deep copy` () {
96
- val clonedPerson = person.deepCopy()
97
- assertThat(clonedPerson).isNotSameAs(person)
98
-
99
- person.address.city = " Bandung"
100
- person.address.street = " Jln. Siliwangi"
101
-
102
- assertThat(clonedPerson.address.city)
103
- .isNotEqualTo(" Bandung" )
90
+ fun `when cloned object then proves that deep copy` (){
91
+ val address = Address (" Jln. Kemasan No 53" , " Yogyakarta" )
104
92
105
- assertThat(clonedPerson. address.street )
106
- .isNotEqualTo( " Jln. Siliwangi " )
107
- }
93
+ val ceo = Person ( " Hangga Aji Sayekti " , address)
94
+ val john = Person ( " John Doe " , address )
95
+ val layla = Person ( " Layla Hinchcliffe " , address)
108
96
109
- @Test
110
- fun `deep copy with copy` (){
111
- val address = Address (" Jln. Kemasan No 53" , " Yogyakarta" )
112
- val person = Person (" Hangga Aji Sayekti" , address)
113
- val company = Company (" Basen Software" , " Tech" , person, listOf (person))
97
+ val company = Company (" Basen Software" , " Tech" , ceo, listOf (john, layla))
114
98
val organization = Organization (" Bekraf" , address, listOf (company))
115
-
116
99
val copiedOrganization = organization.copy(
117
100
headquarters = organization.headquarters.copy(),
118
101
companies = organization.companies.map { company ->
@@ -125,13 +108,18 @@ class CloningObjectUnitTest {
125
108
126
109
val clonedOrganization = organization.clone()
127
110
128
- // Modify the copied organization to verify deep copy
111
+ val clonedSecondaryOrganization = Organization (organization)
112
+
113
+ val coustomDeepCopyOrganization = organization.deepCopy()
114
+
115
+ // Modify the original object to verify deep copy
129
116
organization.name = " New Org Name"
130
117
organization.headquarters.city = " New City"
131
118
organization.companies.first().name = " New Company Name"
132
119
organization.companies.first().ceo.name = " New CEO Name"
133
120
organization.companies.first().employees.first().name = " New Employee Name"
134
121
122
+ // verify deep copy with copy()
135
123
assertThat(copiedOrganization.headquarters.city)
136
124
.isNotEqualTo(" New City" )
137
125
@@ -144,7 +132,7 @@ class CloningObjectUnitTest {
144
132
assertThat(copiedOrganization.companies.first().employees.first().name)
145
133
.isNotEqualTo(" New Employee Name" )
146
134
147
-
135
+ // verify deep copy with clone()
148
136
assertThat(clonedOrganization.headquarters.city)
149
137
.isNotEqualTo(" New City" )
150
138
@@ -156,5 +144,32 @@ class CloningObjectUnitTest {
156
144
157
145
assertThat(clonedOrganization.companies.first().employees.first().name)
158
146
.isNotEqualTo(" New Employee Name" )
147
+
148
+
149
+ // verify deep copy with secondary()
150
+ assertThat(clonedSecondaryOrganization.headquarters.city)
151
+ .isNotEqualTo(" New City" )
152
+
153
+ assertThat(clonedSecondaryOrganization.companies.first().name)
154
+ .isNotEqualTo(" New Company Name" )
155
+
156
+ assertThat(clonedSecondaryOrganization.companies.first().ceo.name)
157
+ .isNotEqualTo(" New CEO Name" )
158
+
159
+ assertThat(clonedSecondaryOrganization.companies.first().employees.first().name)
160
+ .isNotEqualTo(" New Employee Name" )
161
+
162
+ // deep copy
163
+ assertThat(coustomDeepCopyOrganization.headquarters.city)
164
+ .isNotEqualTo(" New City" )
165
+
166
+ assertThat(coustomDeepCopyOrganization.companies.first().name)
167
+ .isNotEqualTo(" New Company Name" )
168
+
169
+ assertThat(coustomDeepCopyOrganization.companies.first().ceo.name)
170
+ .isNotEqualTo(" New CEO Name" )
171
+
172
+ assertThat(coustomDeepCopyOrganization.companies.first().employees.first().name)
173
+ .isNotEqualTo(" New Employee Name" )
159
174
}
160
175
}
0 commit comments