제네릭의 실제 예는 무엇입니까 ?
나는 그것이 ( 모든 수준의 부모 클래스)의 <? super T>모든 수퍼 클래스 를 나타내는 것을 이해합니다 . 그러나 저는이 일반적인 바운드 와일드 카드에 대한 실제 예를 상상하기 위해 정말 고생합니다.TT
나는 <? super T>의미를 이해 하고이 방법을 보았다 :
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));
}
}
이 구조를 사용할 수있는 실제 사용 사례 의 예를 찾고 있으며 그것이 무엇인지에 대한 설명이 아닙니다.
내가 생각할 수있는 가장 쉬운 예는 다음과 같습니다.
public static <T extends Comparable<? super T>> void sort(List<T> list) {
list.sort(null);
}
같은 Collections. 이런 식으로 Dog할 수 Comparable<Animal>있으며 Animal이미 구현 한 경우 Dog아무것도 할 필요가 없습니다.
실제 예를 들어 편집 :
이메일 핑퐁을 한 후 직장에서 실제 사례를 제시 할 수 있습니다 (예!).
우리는 Sink(무엇을하는지 중요하지 않습니다) 라는 인터페이스를 가지고 있습니다 . 아이디어는 물건을 축적 한다는 것입니다. 선언은 매우 사소합니다 (간체).
interface Sink<T> {
void accumulate(T t);
}
분명히 a를 취하고 List요소를 a로 배출 하는 도우미 메서드가 있습니다 Sink(좀 더 복잡하지만 간단하게 만들기 위해).
public static <T> void drainToSink(List<T> collection, Sink<T> sink) {
collection.forEach(sink::accumulate);
}
간단 하죠? 잘...
나는를 가질 수 List<String>있지만 그것을 a로 배출하고 싶습니다. Sink<Object>이것은 우리에게 매우 일반적인 일입니다. 그러나 이것은 실패합니다.
Sink<Object> sink = null;
List<String> strings = List.of("abc");
drainToSink(strings, sink);
이 작업을 수행하려면 선언을 다음과 같이 변경해야합니다.
public static <T> void drainToSink(List<T> collection, Sink<? super T> sink) {
....
}
이 클래스 계층이 있다고 가정합니다. Cat은 Mammal에서 상속하고 다시 Animal에서 상속합니다.
List<Animal> animals = new ArrayList<>();
List<Mammal> mammals = new ArrayList<>();
List<Cat> cats = ...
다음 호출은 유효합니다.
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
그러나 다음 호출은 유효 하지 않습니다.
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
따라서 메서드 시그니처는 단순히 더 구체적인 (상속 계층 구조의 하위) 클래스에서보다 일반적인 클래스 (상속 계층의 상위)로 복사하는 것을 보장합니다.
예를 들어, Collections.addAll메소드 단순화를 살펴보십시오 .
public static <T> boolean addAll(Collection<? super T> c, T... elements) {
boolean result = false;
for (T element : elements)
result |= c.add(element);
return result;
}
여기에서 요소 유형이 요소 유형의 상위 유형 인 모든 컬렉션에 요소를 삽입 할 수 있습니다 T.
하한 와일드 카드가없는 경우 :
public static <T> boolean addAll(Collection<T> c, T... elements) { ... }
다음은 유효하지 않습니다.
List<Number> nums = new ArrayList<>();
Collections.<Integer>addAll(nums , 1, 2, 3);
용어 Collection<T>가보다 제한적 이기 때문 Collection<? super T>입니다.
다른 예시:
Predicate<T><? super T>다음 메소드에서 와일드 카드 를 사용하는 Java의 인터페이스 :
default Predicate<T> and(Predicate<? super T> other);
default Predicate<T> or(Predicate<? super T> other);
<? super T> 더 넓은 범위의 다른 술어를 연결할 수 있습니다. 예를 들면 다음과 같습니다.
Predicate<String> p1 = s -> s.equals("P");
Predicate<Object> p2 = o -> o.equals("P");
p1.and(p2).test("P"); // which wouldn't be possible with a Predicate<T> as a parameter
방법이 있다고 가정합니다.
passToConsumer(Consumer<? super SubType> consumer)
그런 다음 Consumer사용할 수있는 모든 메서드를 사용하여이 메서드를 호출 합니다 SubType.
passToConsumer(Consumer<SuperType> superTypeConsumer)
passToConsumer(Consumer<SubType> subTypeConsumer)
passToConsumer(Consumer<Object> rootConsumer)
예를 들어 :
class Animal{}
class Dog extends Animal{
void putInto(List<? super Dog> list) {
list.add(this);
}
}
그래서 넣을 수 Dog로 List<Animal>또는 List<Dog>:
List<Animal> animals = new ArrayList<>();
List<Dog> dogs = new ArrayList<>();
Dog dog = new Dog();
dog.putInto(dogs); // OK
dog.putInto(animals); // OK
putInto(List<? super Dog> list)방법을 putInto(List<Animal> list)다음과 같이 변경 하는 경우 :
Dog dog = new Dog();
List<Dog> dogs = new ArrayList<>();
dog.putInto(dogs); // compile error, List<Dog> is not sub type of List<Animal>
또는 putInto(List<Dog> list):
Dog dog = new Dog();
List<Animal> animals = new ArrayList<>();
dog.putInto(animals); // compile error, List<Animal> is not sub type of List<Dog>
웹 라디오를 작성 했으므로 MetaInformationObjectPLS 및 M3U 재생 목록의 수퍼 클래스 인 클래스가있었습니다 . 선택 대화가 있었기 때문에 다음과 같이했습니다.
public class SelectMultipleStreamDialog <T extends MetaInformationObject>
public class M3UInfo extends MetaInformationObject
public class PLSInfo extends MetaInformationObject
이 클래스에는 메서드가 public T getSelectedStream()있습니다.
따라서 호출자는 구체적인 유형 (PLS 또는 M3U)의 T를 받았지만 수퍼 클래스에서 작업해야했기 때문에 목록이있었습니다 List<T super MetaInformationObject>.. 결과가 추가되었습니다.
이것이 일반적인 대화가 구체적인 구현을 처리 할 수있는 방법이고 나머지 코드는 수퍼 클래스에서 작동 할 수 있습니다.
그것이 좀 더 명확 해지기를 바랍니다.
이 간단한 예를 고려하십시오.
List<Number> nums = Arrays.asList(3, 1.2, 4L);
Comparator<Object> numbersByDouble = Comparator.comparing(Object::toString);
nums.sort(numbersByDouble);
Hopefully this is a somewhat compelling case: You could imagine wanting to sort the numbers for display purposes (for which the toString is a reasonable ordering), but Number is not itself Comparable.
This compiles because integers::sort takes a Comparator<? super E>. If it took just a Comparator<E> (where E in this case is Number), then the code would fail to compile because Comparator<Object> is not a subtype of Comparator<Number> (due to reasons that your question indicates you already understand, so I won't go into).
Collections serve as a good example here.
As stated in 1, List<? super T> lets you create List that will hold elements of type, that are less derived than T, so it can hold elements that inherit from T, that are type of T and that T inherits from.
On the other hand, List<? extends T> lets you define a List that can hold only elements that inherit from T (in some cases not even of type T).
This is a good example:
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));
}
}
Here you want to project List of less derived type to List of less derived type. Here List<? super T> assures us that all elements from src will be valid in the new collection.
1 : Difference between <? super T> and <? extends T> in Java
Say you have:
class T {}
class Decoder<T>
class Encoder<T>
byte[] encode(T object, Encoder<? super T> encoder); // encode objects of type T
T decode(byte[] stream, Decoder<? extends T> decoder); // decode a byte stream into a type T
And then:
class U extends T {}
Decoder<U> decoderOfU;
decode(stream, decoderOfU); // you need something that can decode into T, I give you a decoder of U, you'll get U instances back
Encoder<Object> encoderOfObject;
encode(stream, encoderOfObject);// you need something that can encode T, I give you something that can encode all the way to java.lang.Object
A few real life examples come to mind for this. The first one I like to bring up, is the idea of a real-world object being used for 'improvised' functionality. Imagine that you have a socket wrench:
public class SocketWrench <T extends Wrench>
The obvious purpose of a socket wrench it so be used as a Wrench. However, if you consider that a wrench could be used in a pinch to pound in a nail, you could have an inheritance hierarchy that looks like this:
public class SocketWrench <T extends Wrench>
public class Wrench extends Hammer
In this scenario, you would be able to call socketWrench.pound(Nail nail = new FinishingNail()), even though that would be considered an atypical use for a SocketWrench.
While all along, the SocketWrench would have access to be able to call methods like applyTorque(100).withRotation("clockwise").withSocketSize(14) if it's being used as a SocketWrench instead of just a Wrench, instead of a Hammer.
참고URL : https://stackoverflow.com/questions/52185915/what-is-a-real-life-example-of-generic-super-t
'Programing' 카테고리의 다른 글
| 웹 페이지 : 버전 설정의 기능은 무엇입니까? (0) | 2020.10.25 |
|---|---|
| 이 Valgrind 경고는 무엇을 의미합니까? (0) | 2020.10.25 |
| Python에서 다소 큰 json 파일 읽기 (0) | 2020.10.25 |
| java : comp / env 란 무엇입니까? (0) | 2020.10.25 |
| Python 3-인코딩 / 디코딩 대 바이트 / Str (0) | 2020.10.25 |