2017-09-18 93 views
6

Bu genel arayüzde güvenli olmayan (T) neden gereklidir? Eğer T kendi başına karşılaştırılabilir ise, yani ExtendedComparable<T> da anlamına gelen ExtendedComparable<super of T>'u uygular, o zaman neden silme işlemi ExtendedComparable<T>'un T?Java Generics'te denetlenmemiş kaliteler nasıl önlenir Karşılaştırılabilir arabirim?

/* @param <T> T must be comparable to itself or any of its superclass 
* (comparables are consumers, thus acc. to the PECS principle 
* = producer-extends,consumer-super we use the bounded wildcard type "super") 
*/ 
public interface ExtendedComparable<T extends ExtendedComparable<? super T>> { 
    Comparator<? super T> getComparator(); 
    default boolean greaterThen(T toCompare) { 
     return getComparator().compare((T) this, toCompare) > 0; 
    } 
} 
+0

Bu gönderi sizin yardımınıza olabilir: https://stackoverflow.com/a/25783345/4867374 –

cevap

5

this aslında sınıfın T örneğidir hatta bunu uzatmak garantisi yoktur çünkü.

Örneğin bu düşünün: T0 extends ExtendComparable<T0> ve T0 T0 süper şudur: ciltli uygun olarak T0 yılında

public class T0 implements ExtendComparable<T0> {...} 
public class T1 implements ExtendComparable<T0> {...} 

ince uyumludur. Bu durumda this, T0'un bir örneğidir; (T)this döküm (böylece (T0)this) anlamlıdır. bağlı T0 bir T1 uygulandığı için

T1 ile beyan da doğrudur, TT0 ikame edilir. Bununla birlikte this, T1 ve T1, ne süper ne de T0 numaralı bir çocuk değildir. Evet, her ikisi de ExtendedCompatible<T0>'u uygular, ancak kardeşler arasında yayın yapamazsınız. Örneğin Tamsayı ve Çifte Sayı Sayısı ama (Integer) new Double(0.0) başarısız. Ayrıca (T)(T0) çevirme işlemi başarısız oluyor.

Yaptığınız varsayım, T'un bildirilen sınıfla aynı olacak şekilde ayarlanacağı ve şu anda bu anlambilgileri zorlamanın bir yolu olmadığıdır. Umarım bu, Java dilinin gelecekteki sürümlerinde bir noktada değişecektir, ancak belki de Java dilinin "görev gücü" nün bunu yapmamasının asıl nedeni vardır.

Tümüyle dökümden kaçınmanın bir yolu vardır, ancak ExtendedCompatible bir arabirim yerine soyut bir sınıf oluşturduğunuzda daha iyidir.

Sen sırayla değeri olarak this geçmelidir değeri uzanan sınıfı tarafından korunan bir yapıcı tarafından belirlenen olacağını tip T nihai alanını ilan edebilir

:

public abstract class ExtendedCompatible<T extends ExtendedCompatible<? super T>> { 
    private final T thiz; 

    protected ExtendedCompatible(final T thiz) { 
    if (this != thiz) throw new IllegalArgumentException("you must pass yourself"); 
    this.thiz = thiz; 
    } 
    ... 

    public class MyExtendedCompatible extends ExtendedCompatible<MyExtendedCompatible> { 
    public MyExtendedCompatible() { 
      super(this); 
    } 
    } 

ödediğiniz fiyat ekstra hafızadır Kendisine aptalca bir referans olması ve ana kurucuya this'un geçirilmesi eklenmiş kod/CPU yükünün tüketimi.

Başka T (this) almak için soyut bir yöntem bildirmek için olacaktır:

// Parent abstract class: 
    protected abstract T getThiz(); 
// Child class... for each class: 
    protected MyChildClass getThiz() { return this; } 
+1

bu çok detaylı ve iyi bir cevap IMO. Yığın taşması, sadece en yüksek oy alan kullanıcılara ödül vermenin bir üne sahiptir, ancak bu gerçekten çok iyi bir şeydir. +1 – Eugene

+0

Teşekkürler. Bu doğru.Arayüzü birçok enum için kullanılacak şekilde tasarladık. Fakat maalesef, önerilen çalışma enerilere uygun değildir, çünkü mirasa destek vermezler ve dolayısıyla soyut bir sınıftan türetilemezler. Aradaki her iki yöntem de oldukça uygun değildir, çünkü arayüzdeki her bir yöntem getThiz()! = Kontrol etmelidir (Java 9'da, en azından tüm bu benzer kontroller özel bir arabirim yöntemine dönüştürülebilir) ve her bir enum getThiz() öğesini uygulamanız gerekir. – ms34449

+0

@ ms34449 Enumlar hakkında ne dersiniz? Sanırım, her bir sabit içindeki yöntemleri geçersiz kılabilirsiniz. EDIT ah! Yani, sabitler karşısında olmayanlar demek istiyorsunuz. –

0

teşekkürler. Valentin haklı. Her iki tür de aynı arabirimi uygulasalar bile, bu, aralarında çalışacakları arasında bir değişiklik yapmaz ve yapmamalıdır. Ve evet, Java'da bildirilen sınıfla aynı sınıfta T'yi geçmeyi zorlayacak hiçbir mekanizma yoktur.

+2

bu, Valentin cevabına yanıt olarak yorum yapmalı ve muhtemelen onun – Eugene