Java 8 อนุญาตวิธีเมธอดอินเตอร์เฟสแบบคงที่
ด้วย Java 8 อินเตอร์เฟสสามารถมีเมธอดแบบสแตติก พวกเขายังสามารถมีวิธีการอินสแตนซ์ที่เป็นรูปธรรม แต่ไม่สามารถเขตข้อมูลอินสแตนซ์
มีคำถามสองข้อจริงๆที่นี่:
- ทำไมในสมัยก่อนไม่สามารถอินเทอร์เฟซไม่ประกอบด้วยวิธีแบบคงที่ได้อย่างไร
- ทำไมวิธีการแบบคงที่ไม่สามารถเขียนทับได้
วิธีการคงที่ในส่วนต่อประสาน
ไม่มีเหตุผลทางเทคนิคที่ชัดเจนว่าเหตุใดอินเทอร์เฟซจึงไม่มีวิธีคงที่ในเวอร์ชันก่อนหน้า สิ่งนี้จะถูกสรุปโดยผู้โพสต์ของคำถามที่ซ้ำกัน วิธีการอินเตอร์เฟซแบบคงที่ได้รับการพิจารณาครั้งแรกเป็นการเปลี่ยนแปลงภาษาขนาดเล็กและจากนั้นมีข้อเสนออย่างเป็นทางการที่จะเพิ่มพวกเขาใน Java 7 แต่มันก็เป็นภายหลังลดลงในเนื่องจากภาวะแทรกซ้อนที่ไม่คาดฝัน
ในที่สุด Java 8 แนะนำวิธีการคงที่ของอินเทอร์เฟซเช่นเดียวกับวิธีการแทนที่ได้ด้วยการใช้งานเริ่มต้น พวกเขายังคงไม่สามารถมีฟิลด์อินสแตนซ์ได้ คุณสมบัติเหล่านี้เป็นส่วนหนึ่งของการรองรับการแสดงออกแลมบ์ดาและคุณสามารถอ่านเพิ่มเติมเกี่ยวกับพวกเขาได้ในส่วน H ของ JSR 335
การเอาชนะวิธีแบบคงที่
คำตอบของคำถามที่สองนั้นซับซ้อนกว่าเล็กน้อย
วิธีการแบบคงที่จะแก้ไขได้ในเวลารวบรวม การกระจายแบบไดนามิกเหมาะสมสำหรับวิธีการอินสแตนซ์ที่คอมไพเลอร์ไม่สามารถกำหนดประเภทที่เป็นรูปธรรมของวัตถุและดังนั้นจึงไม่สามารถแก้ไขวิธีการที่จะเรียกใช้ แต่การเรียกใช้เมธอดสแตติกต้องใช้คลาสและเนื่องจากคลาสนั้นเป็นที่รู้จักกันในชื่อสแตติก - ในเวลาคอมไพล์ - การกระจายแบบไดนามิกไม่จำเป็น
พื้นหลังเล็กน้อยเกี่ยวกับวิธีการทำงานของอินสแตนซ์จำเป็นต้องเข้าใจว่าเกิดอะไรขึ้นที่นี่ ฉันแน่ใจว่าการใช้งานจริงนั้นแตกต่างกันมาก แต่ให้ฉันอธิบายความคิดของวิธีการจัดส่งซึ่งรูปแบบการสังเกตพฤติกรรมที่ถูกต้อง
แกล้งทำเป็นว่าแต่ละคลาสมีตารางแฮชที่แม็พเมธอดลายเซ็นต์ (ชื่อและชนิดพารามิเตอร์) กับ chunk ของรหัสที่แท้จริงเพื่อใช้เมธอด เมื่อเครื่องเสมือนพยายามเรียกใช้เมธอดบนอินสแตนซ์มันจะสอบถามวัตถุสำหรับคลาสและค้นหาลายเซ็นที่ร้องขอในตารางของคลาส หากพบเมธอดเนื้อหามันจะถูกเรียกใช้ มิฉะนั้นจะได้รับชั้นผู้ปกครองของชั้นเรียนและการค้นหาจะถูกทำซ้ำที่นั่น NoSuchMethodError
เงินนี้จนวิธีการที่จะพบหรือไม่มีผู้ปกครองชั้นเรียนซึ่งจะส่งผลให้
หากทั้งคลาสย่อยและคลาสย่อยมีรายการในตารางสำหรับลายเซ็นเมธอดเดียวกันเวอร์ชันของคลาสย่อยจะถูกพบก่อนและเวอร์ชันของคลาสซูเปอร์จะไม่ถูกใช้นี่คือ "แทนที่"
ทีนี้สมมติว่าเราข้ามตัวอย่างของวัตถุและเริ่มต้นด้วยคลาสย่อย ความละเอียดสามารถดำเนินการตามข้างต้นทำให้คุณมีวิธีคงที่ "overridable" การแก้ปัญหาทั้งหมดสามารถเกิดขึ้นได้ในเวลาคอมไพล์อย่างไรก็ตามเนื่องจากคอมไพเลอร์เริ่มจากคลาสที่รู้จักแทนที่จะรอจนกระทั่งรันไทม์เพื่อสอบถามวัตถุประเภทที่ไม่ระบุสำหรับคลาสนั้น ไม่มีจุดใน "การแทนที่" วิธีการคงที่เนื่องจากสามารถระบุคลาสที่มีรุ่นที่ต้องการได้เสมอ
ตัวสร้าง "อินเทอร์เฟซ"
ต่อไปนี้เป็นข้อมูลเพิ่มเติมเล็กน้อยสำหรับการแก้ไขคำถามล่าสุด
IXMLizable
ดูเหมือนคุณต้องการได้อย่างมีประสิทธิภาพอาณัติวิธีการคอนสตรัคเหมือนสำหรับการดำเนินงานของแต่ละคน ลืมเกี่ยวกับการพยายามบังคับใช้สิ่งนี้ด้วยอินเทอร์เฟซเป็นเวลาหนึ่งนาทีและแกล้งทำเป็นว่าคุณมีคลาสที่ตรงตามข้อกำหนดนี้ คุณจะใช้มันอย่างไร?
class Foo implements IXMLizable<Foo> {
public static Foo newInstanceFromXML(Element e) { ... }
}
Foo obj = Foo.newInstanceFromXML(e);
เนื่องจากคุณต้องระบุชื่อประเภทคอนกรีตFoo
เมื่อ "สร้าง" วัตถุใหม่คอมไพเลอร์สามารถตรวจสอบว่ามันมีวิธีการโรงงานที่จำเป็นแน่นอน และถ้าไม่เช่นนั้นจะเป็นอย่างไร ถ้าฉันสามารถดำเนินการIXMLizable
ที่ขาด "คอนสตรัค" และฉันจะสร้างอินสแตนซ์และผ่านมันไปรหัสของคุณก็คือIXMLizable
กับอินเตอร์เฟซที่จำเป็น
การก่อสร้างเป็นส่วนหนึ่งของการดำเนินการไม่ใช่ส่วนต่อประสาน รหัสใด ๆ ที่ทำงานได้ดีกับอินเทอร์เฟซไม่สนใจตัวสร้าง โค้ดใด ๆ ที่เกี่ยวกับคอนสตรัคเตอร์จำเป็นต้องทราบชนิดที่เป็นรูปธรรมอยู่แล้วและสามารถละเว้นอินเตอร์เฟสได้