2018年2月3日 星期六

泛型的extends和super

※賦值

class Animal {}
class Bird extends Animal {}
class Chicken extends Bird {}


List<Animal> listA = new ArrayList<>();
List<Bird> listB = new ArrayList<>();
List<Chicken> listC = new ArrayList<>();

// ------------- 等號右邊沒有 super extends 賦值時 --------------
// 方法的參數有以下左邊的物件時,意思是一樣的
List<? super Animal> a1 = listA;
List<? super Bird> b1 = listA;
List<? super Chicken> c1 = listA;

List<? super Animal> a1s = listB; // x
List<? super Bird> b1s = listB;
List<? super Chicken> c1s = listB;

List<? super Animal> a1ss = listC; // x
List<? super Bird> b1ss = listC; // x
List<? super Chicken> c1ss = listC;
// -------------------------------
List<? extends Animal> a2 = listA;
List<? extends Bird> b2 = listA; // x
List<? extends Chicken> c2 = listA; // x

List<? extends Animal> a2e = listB;
List<? extends Bird> b2e = listB;
List<? extends Chicken> c2e = listB; // x

List<? extends Animal> a2ee = listC;
List<? extends Bird> b2ee = listC;
List<? extends Chicken> c2ee = listC;

// ------------- 等號右邊有 super extends 賦值時 --------------
// 不管是 super 或 extends,都把它當作右邊的物件來看
// super 只能賦值 super;extends 只能賦值 extends
// 被賦值的(等號右邊)沒有 super 或 extends 都會編譯錯誤,但相反可以,如上面的例子
List<? super Animal> qs1 = a1;
List<? super Animal> qs2 = b1; // x
List<? super Animal> qs3 = c1; // x
List<? super Bird> qs4 = a1;
List<? super Bird> qs5 = b1;
List<? super Bird> qs6 = c1; // x
List<? super Chicken> qs7 = a1;
List<? super Chicken> qs8 = b1;
List<? super Chicken> qs9 = c1;

// -------------------------------
List<? extends Animal> qe1 = a2;
List<? extends Animal> qe2 = b2;
List<? extends Animal> qe3 = c2;
List<? extends Bird> qe4 = a2; // x
List<? extends Bird> qe5 = b2;
List<? extends Bird> qe6 = c2;
List<? extends Chicken> qe7 = a2; // x
List<? extends Chicken> qe8 = b2; // x
List<? extends Chicken> qe9 = c2;

※增加元素

Animal a = new Animal();
Bird b = new Bird();
Chicken c = new Chicken();
    
List<? super Animal> listA = new ArrayList<>();
List<? super Bird> listB = new ArrayList<>();
List<? super Chicken> listC = new ArrayList<>();
listA.add(a);
listA.add(b);
listA.add(c);
    
// listB.add(a);
listB.add(b);
listB.add(c);
    
// listC.add(a);
// listC.add(b);
listC.add(c);

※super 可增加元素,取得元素要用 Object;extends 只能取得元素,不能增加元素

※增加元素時,不要看 super 和 extends 關鍵字,會搞混,那是給賦值的時候用的

※如果改用 ? 是無法增加元素的;? 等同 ? extends Object,因為有 extends 就不可以


※注意

1.super 只有傳參時,才表示此類和此類的父類;賦值時最多只表示此類
2.super 轉換後,可以存也可以取
3.extends 只能取得父類的方法,無法存


※super

Animal a = new Animal();
a.setEat("Animal吃");
a.setJump("Animal跳");
    
Bird b = new Bird();
b.setEat("Bird吃");
b.setJump("Bird跳");
b.setFly("Bird飛");
    
Chicken c = new Chicken();
c.setMorning("Chicken說早安");
    
List<? super Animal> list = new ArrayList<>();
list.add(a);
list.add(b);
list.add(c);
    
for (Object o : list) {
    if (o instanceof Chicken) {
        Chicken chicken = (Chicken) o;
        System.out.println(chicken.getMorning());
        continue;
    }
    
    if (o instanceof Bird) {
        Bird bird = (Bird) o;
        System.out.println(bird.getFly());
        continue;
    }
    
    if (o instanceof Animal) {
        Animal animal = (Animal) o;
        System.out.println(animal.getEat());
        continue;
    }
}

※注意順序和 continue,子類在上;父類在下


※extends

public class ExtendsAndSuper {
    public static void main(String[] args) {
        List al= new ArrayList<>();
        Animal a = new Animal();
        a.setEat("Animal吃");
        a.setJump("Animal跳");
        al.add(a);
    
        List bl= new ArrayList<>();
        Bird b = new Bird();
        b.setEat("Bird吃");
        b.setJump("Bird跳");
        b.setFly("Bird飛");
        bl.add(b);
    
        List cl= new ArrayList<>();
        Chicken c = new Chicken();
        c.setEat("Chicken吃");
        c.setMorning("Chicken說早安");
        cl.add(c);
    
        // new ExtendsAndSuper().xxx(al);
        new ExtendsAndSuper().xxx(bl);
        new ExtendsAndSuper().xxx(cl);
    }
    
    private void xxx(List<? extends Bird> list) {
        for (Animal a : list) {
            System.out.println(a.getEat());
            a.setEat("好吃");
            System.out.println(a.getEat());
        }
    }
}

※注意迴圈裡轉換的是 Bird 的父類,還是可以的;但如果迴圈用的是 Bird,還可以用 Bird 的方法

沒有留言:

張貼留言