21 Ağustos 2019 Çarşamba

Cloneable Arayüzü - Shallow Copy Yaratır

Giriş
Cloneable arayüzü kullanılması tavsiye edilmeyen bir arayüz. Deprecate edilmediği halde, deprecate edilmiş gibi kabul edilmesi isteniyor. Metodun imzası şöyle
protected Object clone() throws CloneNotSupportedException
Bazı Özellikleri
1. Clone Metodu Constructor'ı Çağırmaz
clone metodu native çağrılarla direkt JVM heap içinde yeni bir nesne yaratır. Constructor'ımı çağırmak zorunda değildir.
Animal animal = new Animal(101);              //Constructor is executed.

Animal clone=(Animal)animal.clone()     //Constructor is not executed. Why ?
2. Shallow Copy Yaratır
clone metodu nesnenin her bir alanını yeni nesnenin alanına atar. Eğer alan reference type ise shallow copy oluşur. Eğer alan primitive tip veya Immutable ise sorun teşkil etmez.

3. CloneNotSupportedException
Object.clone() metodu eğer nesne Cloneable arayüzünden kalıtmamışsa bu exception'ı atar. Bu işi yapan metod Object sınıfında ve imzası şöyle
protected Object clone() throws CloneNotSupportedException
En Basit Nasıl Kodlarım
Cloneable arayüzünden kalıtır ve clone metodundan ata sınıfı çağırırım. Aslında metodumun ismi clone olmak zorunda değil, çünkü aslında Object.clone () metodunu override etmiyoruz. Amaç sadece Object.clone() metodunu çağırabilmek çünkü Object.clone() normalde protected olduğu için çağrılamaz. Açıklaması şöyle
super.clone() will call it's super.clone() and the chain will continue until the call reaches the clone() method of the Object class, which will create a field by field mem copy of our object and return it back.
Örnek
Şöyle yaparız. Burada shallow copy oluşturulur. Metodumuz CloneNotSupportedException fırlattığı için beni çağıran kişinin bunu yakalaması gerekir.
public class Foo implements Cloneable {

  @Override
  protected Object clone() throws CloneNotSupportedException {
    return super.clone(); 
  }
}
Örnek
Eğer tüm kod benim kontrolümdeyse ve CloneNotSupportedException fırlatılmayacağımdan eminsem şöyle yaparız. Böylece metod imzasındaki throws CloneNotSupportedException kısmından kurtulurum
public Course clone() {
  Course c = null;
  try {
    c = (Course)super.clone();
  } catch (CloneNotSupportedException e) {} // Won't happen
  return c;
}
Örnek - Covariant Return Type
Covariant Return Type yazısına taşıdım.

Örnek
Kopyalamak istediğimiz sınıfın bir tane final alanı olsun. Açıklaması şöyle.
We can not manipulate final fields in Object.clone() because final fields can only be changed through constructors.
Bu sefer copy constructor yöntemini kullanırız. Şöyle yaparız.
public class Person implements Cloneable {
  private final Brain brain; // brain is final since I do not want 
                // any transplant on it once created!
  private int age;
  public Person(Brain aBrain, int theAge) {
    brain = aBrain; 
    age = theAge;
  }
  protected Person(Person another) {
    Brain refBrain = null;
    try {
      refBrain = (Brain) another.brain.clone();
      // You can set the brain in the constructor
    } catch(CloneNotSupportedException e) {}
    brain = refBrain;
    age = another.age;
  }
  public Object clone() {
    return new Person(this);
  }
  ...
}
Kullanım Örnekleri
Basit bir dizi kopyalama örneği
byte[] a = {1,2,3};
byte[] b = (byte[]) a.clone();
System.out.print(a==b); //false verir
Diğer seçenekler ne olabilir ?
Apache Commons ile
 - BeanUtils.cloneBean(object)
 - SerializationUtils (object)
verilen nesneyi serialize edip tekrar okuyarak klonlama imkanı sunuyor.

Ayrıca eğer nesne Fluent Interface şeklindeyse bazı metodlar da kopyasını döndürüyor. "Java Method Naming Convention" şöyle
Prefix Method Type Use
of         static factory Creates an instance where the factory is primarily validating the input                                             parameters, not converting them.
from         static factory Converts the input parameters to an instance of the target class, which                                         may involve losing information from the input.
parse static factory Parses the input string to produce an instance of the target class.
format instance         Uses the specified formatter to format the values in the temporal object                                         to produce a string.
get         instance         Returns a part of the state of the target object.
is         instance         Queries the state of the target object.
with         instance         Returns a copy of the target object with one element changed; this is                                             the immutable equivalent to a set method on a JavaBean.
plus         instance         Returns a copy of the target object with an amount of time added.
minus instance         Returns a copy of the target object with an amount of time subtracted.
to         instance         Converts this object to another type.
at         instance         Combines this object with another.
with(), plus(), minus() gibi metodlar kopya dönebilir.
Örnek
Şöyle yaparızz
kitchen.order(pizzaFactory.getPizza(“crusty”).withToping(“x”).withGarlic());




Hiç yorum yok:

Yorum Gönder