ใครขยายส่วนต่อประสาน? และทำไม?


20

AFAIK คลาสextendsแม่และคลาสimplementsอินเทอร์เฟซของฉัน implements SomeInterfaceแต่ผมทำงานในสถานการณ์ที่ฉันไม่สามารถใช้ มันคือการประกาศประเภททั่วไป ตัวอย่างเช่น:

public interface CallsForGrow {...}

public class GrowingArrayList <T implements CallsForGrow>  // BAD, won't work!
                              extends ArrayList<T> 

ที่นี่ใช้implementsเป็นสิ่งต้องห้าม syntactically ฉันคิดก่อนว่าการใช้อินเทอร์เฟซภายใน <> นั้นเป็นสิ่งต้องห้าม แต่ไม่ใช่ มันเป็นไปได้ฉันมีเพียงแค่ใช้ แทนextends implementsเป็นผลให้ฉัน "ขยาย" อินเทอร์เฟซ ตัวอย่างอื่นนี้ใช้งานได้:

public interface CallsForGrow {...}

public class GrowingArrayList <T extends CallsForGrow>  // this works!
                              extends ArrayList<T> 

สำหรับฉันดูเหมือนว่าจะไม่สอดคล้องกันทางไวยากรณ์ แต่บางทีฉันไม่เข้าใจเรื่อง Java 6 ของ finesses บ้าง? มีสถานที่อื่นที่ฉันควรจะเพิ่มส่วนต่อประสานหรือไม่ อินเทอร์เฟซที่ฉันหมายถึงการขยายควรมีคุณสมบัติพิเศษหรือไม่?

คำตอบ:


25

ในกรณีของตัวแปรประเภททั่วไปคอมไพเลอร์ไม่สนใจจริง ๆ ว่าTเป็นคลาสอินเทอร์เฟซการ enum หรือคำอธิบายประกอบ สิ่งที่สำคัญก็คือมันเป็นประเภทที่มีชุดย่อยและซุปเปอร์ประเภทที่กำหนด

และไม่มีเหตุผลที่จะทำให้ไวยากรณ์ซับซ้อนเพียงเพราะในอีกที่หนึ่ง (ซึ่งคุณใช้อินเทอร์เฟซจริง) ความแตกต่างระหว่างคลาสและอินเทอร์เฟซนั้นมีความเกี่ยวข้อง (ตัวอย่างเช่นถ้าคุณimplementเป็นอินเทอร์เฟซ ไม่จำเป็นถ้าคุณextendเป็นคลาส (ไม่ใช่นามธรรม)

สมมติว่าคุณต้องเขียนimplementsที่นี่จากนั้นคุณต้องใช้ไวยากรณ์แยกต่างหากสำหรับenumค่า (แทนที่จะเป็นแค่การเขียน<E extends Enum<E>>) และคำอธิบายประกอบ (ซึ่งคุณสามารถประกาศได้โดยง่าย<A extends Annotation>)

ที่เดียวที่คุณต้องเขียนimplementsคือจุดที่คุณใช้อินเตอร์เฟซจริง ที่ว่าจุด (และที่จุดเท่านั้น) ความแตกต่างเป็นสิ่งสำคัญเพราะคุณจะต้องใช้วิธีการที่กำหนดไว้ในอินเตอร์เฟซ สำหรับคนอื่น ๆ มันไม่สำคัญว่าสิ่งใดก็ตามAจะได้รับเป็นคลาสพื้นฐานหรืออินเทอร์เฟซที่ใช้งานของB: มันเป็น super-type และนั่นคือทั้งหมดที่สำคัญ

โปรดทราบว่ามีอีกที่หนึ่งที่คุณใช้extendsกับอินเทอร์เฟซ:

interface A {
}

interface B extends A {
}

ณ จุดนี้implementsจะมีความผิดเพราะไม่ได้ใช้B A


หากเราจะใช้ logics ของคุณเราควรใช้ 'ขยาย someInterface' เสมอไม่ใช่เฉพาะใน generics
นักเลง

2
@Gangnus: ไม่เพราะสำหรับผู้ดำเนินการมีความแตกต่างที่เป็นรูปธรรมระหว่างextendsและimplementsเป็นเพียงเมื่อมองปัญหาจากมุมมองของระบบบริสุทธิ์ชนิดที่มีความแตกต่าง
Joachim Sauer

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

1
@Gangnus: ใครบอกว่าTเป็นคลาส? Tสามารถอ้างอิงประเภทอินเตอร์เฟสหรือenumประเภท
Joachim Sauer

1
มาจาก C # การสนทนาทั้งหมดนี้ไร้สาระ เราแสดง supertypes :ของประเภทที่มี และภายใต้หน้าปกอินเทอร์เฟซคือและเป็นคลาสนามธรรมที่มีข้อ จำกัด ของabstractสมาชิกvirtual ( ) ที่ยังไม่ได้ใช้งานเท่านั้นเพื่อให้สามารถรับมรดกได้หลายอย่าง ไม่มีความแตกต่างระหว่างimplementsและextendsแท้จริง พวกเขาทั้งสองสามารถถูกแทนที่ด้วยคำเดียวกัน ( extends) หรือด้วยสัญลักษณ์โดยพลการบางอย่าง ( :) และไม่มีอะไรจะหายไป
ร่า

5

เมื่อ Java 5 และโดยเฉพาะอย่างยิ่ง generics แรกเริ่มให้บริการสำหรับนักพัฒนาที่ลงทะเบียนความสนใจไวยากรณ์แตกต่างกันมาก แทนที่จะSet<? extends Foo>และSet<? super Bar>มันมีและSet<+Foo> Set<-Foo>อย่างไรก็ตามข้อเสนอแนะก็คือว่ามันไม่ชัดเจนว่า+หมายเฉพาะเจาะจงมากขึ้นหรือกว้าง (เรียนเพิ่มเติม) Sun ตอบสนองต่อข้อเสนอแนะนั้นโดยการเปลี่ยนไวยากรณ์ แต่ภายในข้อ จำกัด ของการไม่แนะนำคำหลักใหม่ซึ่งจะเป็นปัญหาสำหรับความเข้ากันได้ย้อนหลัง

ผลที่ได้คือไม่เป็นธรรมชาติเลยทีเดียว ในขณะที่คุณสังเกตเห็นextendsมันมีการใช้งานมากเกินไปเมื่อพูดถึงอินเทอร์เฟซ "การขยาย" ของคลาสซึ่งไม่ใช่ภาษาที่ใช้ในบริบทอื่น และsuperโอเวอร์โหลดหมายถึง "เป็นซูเปอร์คลาสของ" ซึ่งเป็นทิศทางตรงกันข้ามของความสัมพันธ์ที่แสดงออกมาก่อนหน้านี้โดยคำหลักคือการอ้างอิงถึงซูเปอร์คลาส

อย่างไรก็ตามพื้นฐานของสิ่งที่อินเทอร์เฟซไม่ได้รับผลกระทบจากการเปลี่ยนแปลงนี้และจะไม่แนะนำอินเทอร์เฟซพิเศษซึ่งขยายในรูปแบบใหม่


+1 ฉันเห็นและเห็นด้วย แต่โจอาคิมซาวเออร์ได้พบความคิดที่ผิดพลาดของฉันว่าทีจำเป็นต้องมีในชั้นเรียน ดังนั้นคำตอบคือเขา ความเข้าใจของคุณคือหนึ่ง (หรือ 2) ชั้นสูงกว่า :-) ปัญหาของฉันดั้งเดิมมากขึ้น ขอบคุณสำหรับการพัฒนาของฉัน
นักเลง

2

มีข้อเสียทั้งในการอนุญาตและการห้ามไวยากรณ์ดังกล่าวและการอนุญาตมีมากขึ้น

แค่คิดดู

การแยกอินเทอร์เฟซและการใช้งานเป็นหนึ่งในสำนวนการเขียนโปรแกรมพื้นฐาน ด้วยเหตุนี้ไวยากรณ์ที่อนุญาตให้สะกด"ส่วนต่อประสานที่ใช้บางสิ่งบางอย่าง"อาจจะไม่ดีเท่าที่ใช้เครื่องหมายบวกเพื่อแสดงการคูณตัวถูกดำเนินการ


ตกลง. ดังนั้นฉันไม่เข้าใจอะไรจริงๆ ฉันคิดว่ามันน่าจะเป็นมาก แต่คุณยังไม่ได้อธิบายปัญหาเลยขอโทษ T เป็นตัวแทนของคลาส ทำไมในที่เดียวที่ฉันใช้ T ส่วนขยายและในอีกทีใช้?
นักเลง

@Gangnus ในตัวอย่างที่คุณให้ T หมายถึงพิมพ์พารามิเตอร์ซึ่งไม่จำเป็นต้องชั้นเรียน - ดูสิ่งที่โจอาคิมบอกท่านแล้ว การอนุญาตให้มีการดำเนินการจะนำไปสู่ความยุ่งเหยิงเดียวกับที่ฉันพูดถึง
ริ้น

ใช่ฉันเคยเห็นความคิดเห็นของเขาแล้ว มันจะถูกทำเครื่องหมายเป็นคำตอบเมื่อใส่คำตอบ จนถึงที่คุณทั้งคู่จะต้องขอบคุณฉันและ +1
นักเลง

-1

หนึ่งต้องเข้าใจการเขียนโปรแกรมขับเคลื่อนอินเตอร์เฟสเป็นขั้นตอนต่อไปในขณะที่เข้าใจอินเตอร์เฟส มันบอกสิ่งที่ใช้งานจริงของอินเตอร์เฟซ มีบทบาทอะไรในโปรแกรม Java (หรือภาษาอื่น ๆ )


2
คำตอบของคุณตอบข้อกังวลของ OP อย่างไร โปรดแก้ไขคำตอบของคุณให้ชัดเจนยิ่งขึ้น
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.