Clone
Objectives Describe how to make a copy of a reference type • – ICloneable interface – Clone method – Object.MemberwiseClone method • Discuss special cases – string field – reference field – inheritance 2
Motivation: reference type Classes are reference types • – instance is reference/object pair reference type class Person { string name int age; ... } Person a = new Person("Ann", 25); Ann name a age 25 3
Motivation: reference assignment Assignment with reference types copies the reference • – results in aliasing – two references refer to same object Person a = new Person("Ann", 25); Person b; assign b = a; a Ann name age 25 b 4
ICloneable Framework in place to copy instance • – can be useful for reference types – programmer chooses shallow or deep copy semantics cloning framework interface ICloneable { object Clone(); } 5
Clone Class can support cloning • – implement ICloneable interface – code Clone method class Person : ICloneable { Clone method public object Clone() { ... } ... } 6
Using Clone • Call Clone to create new object – return type is object – cast to actual type Person a = new Person("Ann", 25); Person b; clone b = (Person)a.Clone(); 7
MemberwiseClone • Object MemberwiseClone method supports cloning – allocates memory for type being cloned and does shallow copy – sufficient in simple cases – insufficient in complex situations class Object { support for protected object MemberwiseClone() cloning { ... } ... } 8
Implementing Clone • Clone implementation typically uses MemberwiseClone – additional work needed only if shallow copy not sufficient class Person : ICloneable { public object Clone() { MemberwiseClone return MemberwiseClone(); sufficient here } ... } 9
Result of Clone • Clone results in new object – with values copied from old object Person a = new Person("Ann", 25); Person b; clone b = (Person)a.Clone(); Ann name a age 25 name b age 25 10
Clone and string • Not necessary to clone string fields – string is immutable – alias ok Ann name a age 25 name b age 25 11
Reference field Class may have reference field • class Student { int id; reference field Transcript transcript; ... } class Transcript { double gpa; int units; ... } 12
Object with reference field Object with reference field contains only reference • – refers to separate object class Student { public Student(int id, double gpa, int units) { this.id = id; allocate object for reference this.transcript = new Transcript(gpa, units); field } ... } Student a = new Student(4000, 4.0, 50); id 4000 a gpa 4.0 transcript units 50 13
Implementing Clone with reference field Clone of class with reference field more difficult • – use MemberwiseClone to get shallow copy – manually Clone reference field class Student : ICloneable { public object Clone() { allocate memory, Student s = (Student)MemberwiseClone(); shallow copy clone reference field s.transcript = (Transcript)transcript.Clone(); return s; } ... } 14
Result of Clone with reference field Cloning object with reference field can clone referred objects • – to get deep copy Student a = new Student(4000, 4.0, 50); Student b; b = (Student)a.Clone(); id 4000 gpa 4.0 a transcript units 50 id 4000 gpa 4.0 b transcript units 50 15
Cloning fields Reference field should support cloning • – otherwise difficult to clone entire object class Transcript : ICloneable { double gpa; int units; Transcript public object Clone() supports Clone { ... } ... } 16
Inheritance Class may use inheritance • class Person { string name; int age; ... } inheritance class Student : Person { int id; Transcript transcript; ... } 17
Derived object Object of derived type might be quite complicated • – contains fields of base – in addition to its own Student a = new Student("Ann", 25, 4000, 4.0, 50); Ann name age 25 a id 4000 gpa 4.0 transcript units 50 18
Derived Clone • Derived class Clone chains to base class Clone – lets base allocate memory – then clones any of its own reference fields class Student : Person, ICloneable { public object Clone() { chain to base Student s = (Student)base.Clone(); clone reference field s.transcript = (Transcript)transcript.Clone(); return s; } ... } 19
Base Clone Base class clone method • – allocates memory – clones any reference fields in base class • Use MemberwiseClone to allocate memory – correctly creates object of type being cloned class Person : ICloneable { public object Clone() { MemberwiseClone return MemberwiseClone(); sufficient here } ... } 20
Result of cloning derived object Clone of derived object yields new derived object • – both base and derived parts cloned Student a = new Student("Ann", 25, 4000, 4.0, 50); Student b; b = (Student)a.Clone(); Ann name age 25 a id 4000 gpa 4.0 transcript units 50 name age 25 b id 4000 gpa 4.0 transcript units 50 21
Dynamically bound Clone • Clone in inheritance hierarchy should be dynamically bound – ensures correct version when called through base reference Person a = new Student("Ann", 25, 4000, 4.0, 50); Person b; must ensure Student b = a.Clone(); Clone used 22
Virtual clone • Make Clone virtual in inheritance hierarchy – base Clone marked virtual – derived Clone marked override class Person : ICloneable { virtual in base public virtual object Clone() { ... } ... } class Student : Person { public override object Clone() { ... } override in derived ... } 23
Summary • Clone provides way to perform deep copy – must be implemented by programmer – object class provides some support • Cloning can be tricky – reference fields – inheritance 24
Recommend
More recommend