"สวัสดี! ฉันจะไปต่อบทเรียนของ 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
}
"พารามิเตอร์ประเภทเหล่านี้เกี่ยวข้องกับเมธอดโดยเฉพาะ คลาสไม่มีพารามิเตอร์ คุณยังสามารถประกาศเมธอดเหล่านี้แบบสแตติกและเรียกใช้โดยไม่ใช้อ็อบเจกต์"
"ฉันเข้าใจแล้ว จุดของพารามิเตอร์ประเภทในเมธอดนั้นเหมือนกับคลาสหรือไม่"
"ใช่ แต่มีอะไรใหม่"
"อย่างที่คุณทราบอยู่แล้ว คุณสามารถใช้สัญลักษณ์แทนในการประกาศประเภทได้ จากนั้นลองนึกภาพสถานการณ์ต่อไปนี้:"
public void doSomething(List<? extends MyClass> list)
{
for(MyClass object : list)
{
System.out.println(object.getState()); // Everything works well here.
}
}
"แต่ถ้าเราต้องการเพิ่มรายการใหม่ในคอลเลกชัน:"
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) เราจึงเขียนโค้ดที่ไม่ถูกต้องต่อไปนี้:"
List<Object> list;
for(MyClass object : list) // Error!
{
System.out.println(object.getState());
}
"เข้าใจแล้ว ขอบคุณสำหรับบทเรียนที่น่าสนใจ"
"ด้วยความยินดี."