簡體   English   中英

抽象類和泛型中“ this”關鍵字的行為

[英]The behavior of the “this” keyword in abstract classes and generics

考慮以下課程

就序列化而言,我徹底改變了方向,我知道:

abstract class AnimalSerializer<E extends Animal> {
    /**
     * The type E (which extends Animal) is important here. 
     * I want to be able to write data that is specific to a subclass of an animal.
     */
    abstract void writeAnimal(E animal);
    abstract Animal readAnimal();
}

abstract class Animal {
    AnimalSerializer<? extends Animal> serializer;

    Animal(AnimalSerializer<? extends Animal> speciesSerializer) {
        serializer = speciesSerializer;
    }

    void writeAnimalToFile() {
        // This line fails to compile
        serializer.writeAnimal(this);
    }
}

這些類演示了此模式的用法:

class DogSerializer extends AnimalSerializer<Dog> {

    @Override
    void writeAnimal(Dog animal) {
        // Write the stuff that is specific to the dog
        // ...
    }

    @Override
    Animal readAnimal() {
        // Read the stuff specific to the dog, instantiate it, and cast it as an animal.
        // ...
        return null;
    }  
}

class Dog extends Animal {
    String dogTag = "Data specific to dog.";

    Dog() {
        super(new DogSerializer());
    }
}

我的問題與編譯失敗的行有關( serializer.writeAnimal(this) )。 我不得不第一次提高語言規范以了解有關this關鍵字的更多信息,但是我認為問題在於“ this”關鍵字的類型為Animal ,而有界通配符泛型<? extends Animal> <? extends Animal>僅支持屬於Animal子類的類型,而不支持Animal類型本身。

我認為,考慮到無法實例化Animal,編譯器應該知道this關鍵字的類型必須是擴展Animal的對象,並且this關鍵字僅適用於已經存在的對象。

編譯器不知道為什么嗎? 我的猜測是,有一種情況可以解釋為什么不能保證this關鍵字是Animal的子類。

此外,這種模式是否從根本上存在缺陷?

您的serializer通用類型是? extends Animal ? extends Animal 您的this類型是Animal ,也可以視為? extends Animal ? extends Animal 但是這兩個? 是不同的類型。 沒有限制讓編譯器知道它們是同一類型。

例如,我寫了一個Cat

class Cat extends Animal {
  Cat(){
    super(new DogSerializer()); // this is ok for your generic
  }
}

這就是編譯器給您錯誤的原因。

除了Dean所說的之外:您可以使Animal通用: Animal<S extends Animal>然后序列化器變成AnimalSerializer<S> serializer 現在,它引用了Animal的“已知”子類。 並且extends變成了Dog extends Animal<Dog> 不幸的是,沒有辦法阻止Cat extends Animal<Dog>

您仍然必須強制執行以下操作: serializer.writeAnimal((S)this); 但是現在可以這樣做,因為您知道要強制轉換為哪個類。

這是弊端? 在泛型中。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM