Yanıtlar:
Klonun korunduğu gerçeği, clone
yöntemin Cloneable
arayüzde bildirilmediği gerçeği gibi son derece şüphelidir .
Verilerin kopyalarını almak için yöntemi oldukça kullanışsız hale getirir çünkü şunu söyleyemezsiniz :
if(a instanceof Cloneable) {
copy = ((Cloneable) a).clone();
}
Tasarımının Cloneable
artık büyük ölçüde bir hata olarak kabul edildiğini düşünüyorum (aşağıda alıntı). Normalde bir arayüzün uygulamalarını yapabilmeyi isterdim Cloneable
ama mutlakaCloneable
arayüzü yapmam (kullanımına benzer Serializable
). Bu, derinlemesine düşünmeden yapılamaz:
ISomething i = ...
if (i instanceof Cloneable) {
//DAMN! I Need to know about ISomethingImpl! Unless...
copy = (ISomething) i.getClass().getMethod("clone").invoke(i);
}
Josh Bloch'un Etkili Java'sından Alıntı :
"Klonlanabilir arabirim, nesnelerin klonlamaya izin verdiklerinin reklamını yapmaları için bir mixin arabirimi olarak tasarlandı. Ne yazık ki bu amaca hizmet etmiyor ... Bu, taklit edilecek bir arabirim değil, oldukça alışılmadık bir arabirim kullanımıdır ... Arayüzün bir sınıf üzerinde herhangi bir etkiye sahip olması için, o ve tüm üst sınıflarının oldukça karmaşık, uygulanamaz ve büyük ölçüde belgelenmemiş bir protokole uyması gerekir "
Serializable
- uygulanıp uygulanmayacağına karar vermek uygulamalara bağlıdır Serializable
. Bunu Cloneable
genişletiyordum - bir arayüzün genişletmesi gereken bir şey değil - ama bir arayüzün uygulanması özgürdür Cloneable
. Sorun şu ki, arayüz türünde bir parametreniz varsa, ona klonlanabilir olup olmadığını sormanız; ama o zaman onu gerçekten klonlayamazsınız!
Klonlanabilir arayüz, sınıfın klonu destekleyebileceğini belirten bir işarettir. Yöntem korumalıdır çünkü onu nesne üzerinde çağırmamalısınız, onu genel olarak geçersiz kılabilirsiniz (ve yapmalısınız).
Güneşten:
Object sınıfında, clone () yöntemi korumalı olarak bildirilir. Yaptığınız tek şey Cloneable'ı uygulamaksa, yalnızca aynı paketin alt sınıfları ve üyeleri nesnede clone () işlevini çağırabilir. Herhangi bir paketteki herhangi bir sınıfın clone () yöntemine erişmesini sağlamak için, aşağıda yapıldığı gibi onu geçersiz kılmanız ve genel olarak ilan etmeniz gerekir. (Bir yöntemi geçersiz kıldığınızda, onu daha az özel yapabilir ancak daha özel yapamazsınız. Burada, Object'teki korumalı clone () yöntemi genel bir yöntem olarak geçersiz kılınır.)
Set
clone
korumalıdır, çünkü mevcut sınıfa özgü olması için geçersiz kılınması gereken bir şeydir. clone
Herhangi bir nesneyi klonlayacak bir genel yöntem oluşturmak mümkün olsa da, bu, özellikle ona ihtiyaç duyan sınıf için yazılmış bir yöntem kadar iyi olmayacaktır.
Clone yöntemi doğrudan herhangi bir nesne üzerinde kullanılamaz, bu nedenle alt sınıf tarafından geçersiz kılınması amaçlanmıştır.
Tabii ki halka açık olabilir ve klonlama mümkün olmadığında uygun bir istisna yapabilir, ancak bunun yanıltıcı olacağını düşünüyorum.
Şu anda klonun uygulanma şekli, neden klon kullanmak istediğinizi ve nesnenizin nasıl klonlanmasını istediğinizi düşünmenizi sağlar.
Korumalıdır çünkü varsayılan uygulama, kurucuyu atlatarak tüm alanların (özel dahil) basit bir üye kopyası oluşturur . Bu, bir nesnenin ilk etapta işlemek üzere tasarlanabileceği bir şey değildir (örneğin, paylaşılan bir listede oluşturulan nesne örneklerini veya benzer bir şeyi izleyebilir).
Aynı nedenden ötürü, varsayılan uygulaması, clone()
çağrıldığı nesne uygulanmazsa atar Cloneable
. Bu, geniş kapsamlı sonuçları olan potansiyel olarak güvenli olmayan bir işlemdir ve bu nedenle sınıfın yazarının açıkça kabul etmesi gerekir.
Cloneable'ın javadoc'undan.
* By convention, classes that implement this interface (cloneable) should override
* <tt>Object.clone</tt> (which is protected) with a public method.
* See {@link java.lang.Object#clone()} for details on overriding this
* method.
* Note that this interface does <i>not</i> contain the <tt>clone</tt> method.
* Therefore, it is not possible to clone an object merely by virtue of the
* fact that it implements this interface. Even if the clone method is invoked
* reflectively, there is no guarantee that it will succeed.
Böylece her nesnede klon çağırabilirsiniz, ancak bu size çoğu zaman istediğiniz sonuçları veya bir istisnayı vermez. Ancak, yalnızca klonlanabilir uygularsanız teşvik edilir.
IMHO bu kadar basit:
#clone
klonlanamayan nesnelere çağrılmamalıdır, bu nedenle kamuya açıklanmaz#clone
Object
Doğru sınıfın sığ kopyasını elde etmek için Cloneable'ı uygulayan ob alt sınıfları tarafından çağrılmalıdırAlt sınıflar tarafından çağrılabilen, ancak diğer sınıflar tarafından çağrılamayan yöntemler için doğru kapsam nedir?
Bu protected
.
Cloneable
Elbette uygulayan sınıflar bu yöntemi herkese açık hale getirecek ve böylece diğer sınıflardan çağrılabilecektir.
Clone () yönteminde dahili olarak bir 'Cloneable örneğinin olup olmadığı' denetimi vardır. Bu, Java ekibinin clone () method.clone () yönteminin uygunsuz kullanımını kısıtlayacağını düşünebileceği şekilde korunur, yani yalnızca alt sınıflar tarafından erişilebilir. Object, tüm alt sınıfların ebeveyn sınıfı olduğundan, Clone () yöntemi, yukarıdaki 'Cloneable örneği' kontrolüne sahip değilsek, tüm sınıflar tarafından kullanılabilir. Java ekibinin, clone () yönteminde 'Cloneable örneğidir' kontrolünü yaptırarak clone () 'un uygunsuz kullanımını kısıtlamayı düşünmesinin nedeni budur.
Bu nedenle, cloneable uygulayan sınıflar, Object sınıfının clone () yöntemini kullanabilir.
Ayrıca korumalı hale getirdiği için, yalnızca klonlanabilir arabirimi uygulayan alt sınıflar tarafından kullanılabilir. Herkese açık hale getirmek istiyorsak, bu yöntemin alt sınıf tarafından kendi uygulamaları ile geçersiz kılınması gerekir.
Evet, karşılaştığım sorunla aynı. Ama bu kodu uygulayarak çözüyorum
public class Side implements Cloneable {
public Side clone() {
Side side = null;
try {
side = (Side) super.clone();
} catch (CloneNotSupportedException e) {
System.err.println(e);
}
return side;
}
}
Tıpkı birinin söylediği gibi.
Güneş geliştiricileri de sadece insandır ve gerçekten de klon yöntemini korumalı olarak uygulamak için büyük bir hata yaptılar, ArrayList'te işlevsiz bir klon yöntemi uyguladıklarıyla aynı hata! Bu nedenle, genel olarak, deneyimli Java programcılarının bile klon yöntemi hakkında çok daha derin bir yanlış anlaşılması vardır.
Bununla birlikte, son zamanlarda herhangi bir nesneyi tüm içeriği ile kopyalamak için hızlı ve kolay bir çözüm buldum, nasıl oluşturulduğu ve ne içerdiğine bakılmaksızın, cevabıma buradan bakın: Object.clone () kullanımında hata
Yine, Java JDK çerçevesi mükemmel bir düşünce sergiliyor:
Klonlanabilir arayüz bir "genel T klonu ()" içermez; yöntem çünkü bir örneğin klonlanmasına izin veren bir öznitelik (örn. Seri hale getirilebilir) gibi davranır.
Bu tasarımda yanlış bir şey yok çünkü:
Object.clone (), özel tanımlı sınıfınızla istediğinizi yapmayacaktır.
Myclass varsa Cloneable => "public MyClass clone ()" ile clone () üzerine yazarsınız
MyInterface, Cloneable'ı genişletir ve MyInterface'i uygulayan bazı MyClasses'ınız varsa: "public MyInterface clone ()"; arabirimde ve MyInterface nesnelerini kullanan her yöntem, MyClass sınıfı ne olursa olsun onları klonlayabilecektir.