―― À la suite de l'utilisation de PHP pendant plusieurs années, ma connaissance de Java a diminué, je vais donc la rappeler et la résumer (principalement sur la partie compliquée du type)
--Assomption) Quand le chien étend l'animal --Séquence est covariante) Chien [] est un sous-type d'Animal [](= assignable)
--Une classe qui a un paramètre de type (tel que T) dans sa déclaration est appelée une classe générique.
class Animal {
public int getAge() {
return 3;
}
}
class Dog extends Animal {
@Override
public int getAge() {
return 33;
}
//Méthodes uniquement dans la classe Dog
public String getName() {
return "john";
}
}
class AnimalBox<T extends Animal> {
T someAnimal;
public AnimalBox(T animal) {
someAnimal = animal;
}
public int getAge() {
return someAnimal.getAge();
}
}
―― ~~ Cependant, dans ce cas, si vous le faites simplement de type Animal, vous pouvez insérer Dog et faire de même, donc je ne sais pas comment l'utiliser correctement (c'est un problème) ~ ~ ――Pour le problème ci-dessus, si vous implémentez public T get (), le type générique peut être retourné par Dog, mais AnimalBox2 ne peut renvoyer que Animal.Dans le commentaire, j'ai expliqué un exemple de la différence.
//C'est bon
class AnimalBox2 {
Animal someAnimal;
public AnimalBox2(Animal animal) {
someAnimal = animal;
}
public int getAge() {
return someAnimal.getAge();
}
}
class Box<T> {
T someValue;
List<T> history = new ArrayList<>();
public Box(T v) {
someValue = v;
}
public T get() {
return someValue;
}
public void selectOne(Box<? extends T> box) {
history.add(box.get());
}
}
Dog d = new Dog();
Animal a = d; //Bien qu'il s'agisse d'un type différent, il peut être attribué car il s'agit d'une sous-classe
System.out.println(a.getClass().getName()); //Dog
System.out.println(a.getAge()); //33
System.out.println(d.getName()); //john
System.out.println(a.getName()); //error: cannot find symbol
--D'en haut)
SpaceDog sd = new Dog(); //Dog cannot be converted to SpaceDog
―― Et si le type générique est covariant?
List<SpaceDog> spaceDogList = new ArrayList<>();
List<Dog> dogList = spaceDogList; //(Si c'était un co-changement)Bien qu'il s'agisse d'un type différent, il peut être attribué car il s'agit d'une sous-classe
dogList.add(new Dog());
--Dog a entré List \
«Ce n'est pas devenu. Cela n'entraîne pas d'erreur de compilation, mais une erreur d'exécution.
SpaceDog[] spaceDogArray = new SpaceDog[1];
Dog[] dogArray = spaceDogArray;
dogArray[0] = new Dog(); //Erreur d'exécution:java.lang.ArrayStoreException: Dog
――Vous ne comprenez peut-être pas ce que vous dites ―― ↓ Dans un tel cas, la variable a peut-elle être utilisée pour détruire la composition type?
Dog d = new Dog();
Animal a = d;
//Je veux en quelque sorte utiliser la variable a pour que la variable d soit en difficulté pour la commodité de l'interprétation des types.
«Je ne peux penser qu'à créer et à écraser, mais d n'est pas un problème car il n'est pas écrasé et est créé dans un autre emplacement.
Dog d = new Dog();
Animal a = d;
System.out.println(d); //Dog@77468bd9
System.out.println(a); //Dog@77468bd9
a = new Animal();
System.out.println(a); //Animal@12bb4df8
List<Dog> dogList = new ArrayList<>();
dogList.add(new Dog());
dogList.add(new SpaceDog());
――Je ne peux pas faire ça
class Box<T> {
T someValue;
List<T> history = new ArrayList<>();
public Box(T v) {
someValue = v;
}
public void set(T v) {
someValue = v;
}
public T get() {
return someValue;
}
public void selectOne(Box<T> box) {
history.add(box.get());
}
}
Box<Dog> dogBox = new Box<>(new Dog());
Box<SpaceDog> spaceDogBox = new Box<>(new SpaceDog());
dogBox.selectOne(spaceDogBox); //Erreur de compilation:Box<Dog>Et boîte<SpaceDog>Est un autre type
――Vous pouvez le faire de cette façon
public void selectOne(Box<? extends T> box) {
history.add(box.get());
}
――Pourquoi le type est-il cohérent?
--Il est interdit de transmettre une valeur autre que null à la méthode set (si Dog peut être défini, someValue of Box \
public void selectOne(Box<? extends T> box) {
history.add(box.get());
box.set(someValue); //Erreur de compilation
}
--Si vous pensez que \ <? Etend T> ci-dessus "soulage (de manière covariante) l'invariance des types génériques en limitant la fonction des variables pour récupérer les valeurs"
――Si une classe normale résume les attributs et les comportements d'objets spécifiques (animaux, chiens, etc.), le type générique est imaginé comme enveloppant le résumé *** dans un contexte différent. Faire --Il y a deux mondes, l'un est le monde des classes normales (Animal, Dog, SpaceDog) qui sont des paramètres de type, et l'autre est le monde des contextes (List, Queue, Box, Optional ...) que les types génériques tentent d'exprimer. --Les actions de "donner une valeur au contexte" et "récupérer la valeur du contexte" se produisent, mais si elle reste inchangée, la relation d'héritage des paramètres de type ne peut pas être utilisée, il y a donc de grandes restrictions.
Recommended Posts