"สวัสดี! ฉันจะไปต่อบทเรียนของ Ellie เกี่ยวกับยาชื่อสามัญ พร้อมฟังหรือยัง"

"ใช่."

"งั้นเรามาเริ่มกันเลย"

"สิ่งแรกที่คุณต้องรู้คือเมธอดของคลาสสามารถมีพารามิเตอร์ประเภทของตัวเองได้เช่นกัน"

"ฉันรู้."

"ไม่ ฉันหมายถึงพารามิเตอร์ประเภทของตัวเองโดยเฉพาะ: "

ตัวอย่าง
class Calculator
{
  T add(T a, T b); // Add
  T sub(T a, T b); // Subtract
  T mul(T a, T b); // Multiply
  T div(T a, T b); // Divide
}

"พารามิเตอร์ประเภทเหล่านี้เกี่ยวข้องกับเมธอดโดยเฉพาะ คลาสไม่มีพารามิเตอร์ คุณยังสามารถประกาศเมธอดเหล่านี้แบบสแตติกและเรียกใช้โดยไม่ใช้อ็อบเจกต์"

"ฉันเข้าใจแล้ว จุดของพารามิเตอร์ประเภทในเมธอดนั้นเหมือนกับคลาสหรือไม่"

"ใช่ แต่มีอะไรใหม่"

"อย่างที่คุณทราบอยู่แล้ว คุณสามารถใช้สัญลักษณ์แทนในการประกาศประเภทได้ จากนั้นลองนึกภาพสถานการณ์ต่อไปนี้:"

ตัวอย่างที่ 1
public void doSomething(List<? extends MyClass> list)
{
 for(MyClass object : list)
 {
  System.out.println(object.getState()); // Everything works well here.
 }
}

"แต่ถ้าเราต้องการเพิ่มรายการใหม่ในคอลเลกชัน:"

ตัวอย่างที่ 2
public void doSomething(List<? extends MyClass> list)
{
 list.add(new MyClass()); // Error!
}

"ปัญหาคือในกรณีทั่วไป เมธอด doSomething อาจส่งผ่านรายการที่มีองค์ประกอบไม่ใช่วัตถุ MyClass แต่เป็นวัตถุของคลาสย่อยของ MyClass แต่คุณไม่สามารถเพิ่มวัตถุ MyClass ในรายการดังกล่าวได้!"

"อา ถ้าอย่างนั้นจะทำอะไรได้บ้าง"

"ไม่มีอะไร ในสถานการณ์นี้ คุณไม่สามารถทำอะไรได้ แต่สิ่งนี้ทำให้ผู้สร้างของ Java มีบางอย่างที่ต้องคิด และพวกเขาก็คิดคีย์เวิร์ดใหม่ขึ้นมา: super "

"ไวยากรณ์มีลักษณะเกือบเหมือนกัน:"

List<? super MyClass> list

แต่มีความแตกต่างที่สำคัญระหว่างส่วนต่อขยายและส่วนสูง

"«? ขยาย T» หมายความว่าคลาสต้องเป็นลูกหลานของ T"

"«? super T» หมายความว่าคลาสต้องเป็นบรรพบุรุษของ T"

"Holy moly แล้วนี่ใช้ที่ไหน"

"«? super T» ใช้เมื่อเมธอดเกี่ยวข้องกับการเพิ่มคอลเลกชันของวัตถุ T ในกรณีนี้ อาจเป็นคอลเลกชันของวัตถุ T หรือบรรพบุรุษใดๆ ของ T"

"ออบเจ็กต์ AT สามารถกำหนดให้กับตัวแปรอ้างอิงที่มีประเภทเป็นบรรพบุรุษของ T"

"พูดตามตรง วิธีนี้ไม่ได้ใช้บ่อยนัก ยิ่งไปกว่านั้น ยังมีข้อบกพร่อง ตัวอย่างเช่น:"

ตัวอย่าง
public void doSomething(List<? super MyClass> list)
{
 for(MyClass object : list) // Error!
 {
  System.out.println(object.getState());
 }
}
public void doSomething(List<? super MyClass> list)
{
 list.add(new MyClass()); // Everything works well here.
}

"ตอนนี้ตัวอย่างแรกใช้ไม่ได้"

"เนื่องจาก list อาจเป็น List<Object> (Object คือ superclass ระดับบนสุดของ MyClass) เราจึงเขียนโค้ดที่ไม่ถูกต้องต่อไปนี้:"

ตัวอย่างที่ 1
List<Object> list; 

for(MyClass object : list) // Error!
{ 
 System.out.println(object.getState()); 
}

"เข้าใจแล้ว ขอบคุณสำหรับบทเรียนที่น่าสนใจ"

"ด้วยความยินดี."