Giriş
<? super T> kuralını anlamak için PECS kuralını anlamak gerekir.
<? super T> kuralını anlamak için PECS kuralını anlamak gerekir.
Açıklaması şöyle
Useful when defined as method argument where method implementation only writes data to collectionYou can add only specified type of object and null to lower bounded collection.
Kalıtım hiyerarşisinde üstten veya alttan sınırlandırılmış wildcard anlamına gelir. Java'daki kurallar PECS (Producer extends Consumer super) kuralı ile hatırlanabilir. Kural kısaca şu anlama geliyor.
1. Eğer liste dolaşılacaksa - yani producer ise - extends ile kullan.
2. Eğer listeye yeni bir şey eklenecekse - yani consumer ise - super ile kullan.
3. Eğer nesne girdi olarak kullanılıp yeni bir sonuç dönülecekse yani consumer ise - super - kullan.
Doldurmak İçin Tanımlama
Yukarıdaki PECS açıklamasından yola çıkarak listeye bir şey ekleneceğini anlayabiliriz. Liste şöyle tanımlanır.
List<? super Number> list = null;
Okumak
Elimizde şöyle bir kod olsun.
ArrayList<? super A> listOfSuperA = new ArrayList<>();
Bu koddan sadece Object okuyabiliriz. Görmek için şöyle yaparız.// invalid, because listOfSuperA could contain Objects, which are not convertible to A
A a2 = listOfSuperA.get(0);
// valid, because whatever is in listOfSuperA, it can be converted to Object
aloObject o2 = listOfSuperA.get(0);
Comparator Örnekleri
Comparator nesneleri genellikle super ile tanımlanıyor. Açıklaması şöyle. Yani consumer bir nesne alır ve bir sonuç döner.Comparator that we used in SortingService is a perfect example. This interface has one method that accepts a generic type and returns a concrete one. A typical example of a consumer. Other ones are Predicate, Consumer, Comparable, and many others from java.util package. Mostly all of these interfaces should be used with ? super T.
Örnek
Şöyle yaparız. Burada Comparator super ile kullanılıyor çünkü bir producer. Bir nesne alıp bir sonuç döndürüyor.
interface SortingService {<T> void sort(List<T> list, Comparator<? super T> comparator);}// universal comparatorComparator<Employee> comparator = ...;List<Manager> managers = ...;List<Accountant> accountants = ...;List<SoftwareEngineer> engineers = ...;// All these examples compile successfulllysortingService.sort(managers, comparator);sortingService.sort(accountants, comparator);sortingService.sort(engineers, comparator);
Map Örnekleri
Örnek
Map ArrayList alacak alacak diye tanımlanıyor. Object veya List eklemeye çalışmak hatadır
List<Object> list = new ArrayList();
Map<Object, ? super ArrayList> m = new HashMap<Object, ArrayList>();
m.put(1, new Object()); //Error
m.put(2, list); //Error
Kullanmak için şöyle yapmak gerekir.ArrayList list = new ArrayList();
Map<Object, ? super List> m = new HashMap<Object, List>();
m.put(2, list);
Liste Örnekleri
Örnek
Basit bir nesne hiyerarşimiz olsun. Shape sınıfının kendisi veya Shape sınıfından kalıtan Circle, Square, Rectangle gibi sınıflar listeye eklenebilir. Listeyi okumaya çalışmak hatalıdır.
public void testContraVariance(List<? super Shape> list) {
list.add(new Shape());//compiles
list.add(new Circle());//compiles
list.add(new Square());//compiles
list.add(new Rectangle());//compiles
Shape shape= list.get(0); // does not compile
}
Elimizde şöyle bir kod olsun. dest veri yapısına T'den kalıtan nesneler eklenebilir.
public class Collections {
public static <T> void copy(List<? super T> dest, List<? extends T> src) {
for (int i = 0; i < src.size(); i++)
dest.set(i, src.get(i));
}
}
Elimizde şöyle bir kod olsunList<Animal> animals = new ArrayList<>();
List<Mammal> mammals = new ArrayList<>();
List<Cat> cats = ...
Şu kod derlenir.Collections.copy(animals, mammals); // all mammals are animals
Collections.copy(mammals, cats); // all cats are mammals
Collections.copy(animals, cats); // all cats are animals
Collections.copy(cats, cats); // all cats are cats
Şu kod derlenmez.Collections.copy(mammals, animals); // not all animals are mammals
Collections.copy(cats, mammals); // not all mammals are cats
Collections.copy(cats, animals); // mot all animals are cats
Hiç yorum yok:
Yorum Gönder