เหตุใดจึงไม่สามารถขยายคำอธิบายประกอบใน Java ได้


227

ฉันไม่เข้าใจว่าทำไมไม่มีการสืบทอดในหมายเหตุประกอบ Java เช่นเดียวกับคลาส Java ฉันคิดว่ามันจะมีประโยชน์มาก

ตัวอย่างเช่น: ฉันต้องการทราบว่าคำอธิบายประกอบที่กำหนดเป็นตัวตรวจสอบความถูกต้องหรือไม่ ด้วยการสืบทอดฉันสามารถย้อนกลับไปที่ซูเปอร์คลาสเพื่อทราบว่าการเพิ่มความคิดเห็นนี้ขยายไปValidatorAnnotationหรือไม่ มิฉะนั้นฉันจะทำสิ่งนี้ได้อย่างไร

ดังนั้นใครสามารถให้เหตุผลฉันสำหรับการตัดสินใจออกแบบนี้ได้หรือไม่?


2
หมายเหตุ BTW ว่าคำอธิบายประกอบทั้งหมดจะขยายออกไปjava.lang.annotation.Annotationเช่นคำอธิบายประกอบใด ๆinstanceofถึงแม้ว่าข้อเท็จจริงนี้จะไม่ได้ประกาศอย่างชัดเจน
TomášZáluský

คำตอบ:


166

เกี่ยวกับสาเหตุที่ไม่ได้ออกแบบมาในแบบที่คุณสามารถหาคำตอบในคำถามที่พบบ่อยการออกแบบJSR 175ที่มันพูดว่า:

ทำไมคุณไม่สนับสนุนการพิมพ์ย่อยหมายเหตุประกอบ (ที่ประเภทคำอธิบายประกอบประเภทหนึ่งขยายอีก)

มันทำให้ระบบประเภทคำอธิบายประกอบมีความซับซ้อนและทำให้การเขียน“ เครื่องมือเฉพาะ” นั้นยากขึ้น

...

“ เครื่องมือเฉพาะ” - โปรแกรมที่เคียวรีชนิดคำอธิบายประกอบที่รู้จักของโปรแกรมภายนอกโดยพลการ ตัวอย่างเช่นเครื่องกำเนิด Stub อยู่ในหมวดหมู่นี้ โปรแกรมเหล่านี้จะอ่านคลาสที่มีคำอธิบายประกอบโดยไม่โหลดลงในเครื่องเสมือน แต่จะโหลดอินเตอร์เฟสของคำอธิบายประกอบ

ดังนั้นใช่ฉันเดาเหตุผลก็แค่จูบ อย่างไรก็ตามดูเหมือนว่าปัญหานี้ (พร้อมกับคนอื่น ๆ ) จะถูกมองเป็นเป็นส่วนหนึ่งของJSR 308และคุณยังสามารถหาทางเลือกคอมไพเลอร์ที่มีฟังก์ชั่นนี้ได้รับการพัฒนาแล้วโดยงัด Ricken


67
บางทีฉันอาจโง่ แต่ฉันคิดว่ามันน่าเสียดายที่ไม่สามารถขยายคำอธิบายประกอบเพียงเพื่อ "ทำให้มันง่าย" อย่างน้อยนักออกแบบ Java ก็ไม่ได้คิดเหมือนกันเกี่ยวกับการสืบทอดคลาส: P
sinuhepop

2
Java 8 M7 ดูเหมือนจะไม่รองรับหมายเหตุประกอบย่อย น่าเสียดาย
Ceki

2
@assylias JEP 104 ไม่เกี่ยวกับการทำให้คำอธิบายประกอบคลาสย่อยเป็นไปได้ JEP 104 ถูกนำไปใช้ใน Java 8 แต่ยังคงเป็นไปไม่ได้ที่จะทำหมายเหตุประกอบคลาสย่อย (ทำให้คำอธิบายประกอบหนึ่งขยายคำอธิบายประกอบอื่น)
Jesper

71

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

คิดถึงปัญหาทั้งหมดเมื่อคุณแนะนำความหลากหลายและการสืบทอดให้กับหมายเหตุประกอบ (เช่นเกิดอะไรขึ้นเมื่อคำอธิบายประกอบย่อยเปลี่ยนข้อมูลกำกับ meta-annotation เช่นการเก็บรักษา)

และทั้งหมดนี้เพิ่มความซับซ้อนให้กับกรณีการใช้งาน?

คุณต้องการที่จะรู้ว่าคำอธิบายประกอบที่กำหนดเป็นของหมวดหมู่หรือไม่?

ลองสิ่งนี้:

@Target(ElementType.ANNOTATION_TYPE)
public @interface Category {
    String category();
}

@Category(category="validator")
public @interface MyFooBarValidator {

}

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

ดังนั้นKISSคือเหตุผลที่ไม่แนะนำระบบประเภทเมตากับภาษาจาวา

[แก้ไข ps]

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

@Target(ElementType.ANNOTATION_TYPE)
public @interface Category {
    AnnotationCategory[] category();
}
public enum AnnotationCategory {
    GENERAL,
    SEMANTICS,
    VALIDATION,
    ETC
}

@Category(category={AnnotationCategory.GENERAL, AnnotationCategory.SEMANTICS})
public @interface FooBarAnnotation {

}


ไม่ทำงานจะพิมพ์เท็จ:@Target(ElementType.ANNOTATION_TYPE) @Retention(RetentionPolicy.RUNTIME) @interface C {}; @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @C public @interface F {} class a{ @F public void S() {} } @Test public void blahTest() throws NoSuchMethodException { Method m = a.class.getMethod("S"); System.out.println(m.isAnnotationPresent(C.class)); }
1615664

เรากำลังใส่คำอธิบายประกอบ # S มีการเพิ่มความคิดเห็น F. F มีการทำหมายเหตุประกอบเองด้วย C ลองดู
alphazero

ใช่ถูกต้องแล้ว แต่มีวิธีทำอย่างนั้นมากกว่าที่จะอ่านผ่านพร็อกซีหมายเหตุหรือไม่
user1615664

12

ในแง่ที่คุณมีอยู่แล้วพร้อมคำอธิบายประกอบ - meta Annotations หากคุณเพิ่มคำอธิบายประกอบด้วยข้อมูลเมตานั่นคือในหลาย ๆ วิธีเทียบเท่ากับการขยายส่วนต่อประสานเพิ่มเติม คำอธิบายประกอบเป็นส่วนต่อประสานดังนั้นรูปแบบความหลากหลายไม่เข้ามามีบทบาทจริงๆและเนื่องจากเป็นแบบคงที่ในธรรมชาติจึงไม่มีการกระจายแบบไดนามิกรันไทม์

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

กรณีใช้งานเพียงอย่างเดียวที่ฉันเห็นได้ว่าการสืบทอดจะช่วยได้ถ้าคุณต้องการให้คำอธิบายประกอบเป็นแบบ super แต่จะเพิ่มความซับซ้อนทั้งหมดเนื่องจากวิธีหรือประเภทที่กำหนดอาจมีคำอธิบายประกอบสองแบบ หมายความว่าอาร์เรย์จะต้องถูกส่งคืนแทนที่จะเป็นวัตถุเดียว

ดังนั้นฉันคิดว่าคำตอบที่ดีที่สุดคือกรณีการใช้งานนั้นลึกลับและซับซ้อนกว่ากรณีการใช้มาตรฐานทำให้ไม่คุ้มค่า


5

ผู้ออกแบบการสนับสนุนการเพิ่มความคิดเห็นของ Java ได้สร้าง "การทำให้เข้าใจง่าย" จำนวนหนึ่งเพื่อความเสียหายของชุมชน Java

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

  2. หนึ่งหมายเหตุประกอบของประเภทที่กำหนดต่อไซต์ สิ่งนี้นำไปสู่รูปแบบการเพิ่มความคิดเห็นที่ไม่จำเป็นโดยสมบูรณ์ @Validation และ @Validations, @Image และ @Images เป็นต้น

อันที่สองกำลังถูกแก้ไขใน Java 8 แต่มันสายเกินไป เฟรมเวิร์กจำนวนมากได้รับการเขียนตามสิ่งที่เป็นไปได้ใน Java 5 และตอนนี้หูด API เหล่านี้อยู่ที่นี่เป็นเวลานาน


1
ไม่เพียงแค่นั้นยังทำให้ไม่สามารถกำหนดคุณสมบัติที่มีแอตทริบิวต์ซ้อนกันซ้ำ - ซึ่งสนับสนุนโดย XML schema สิ่งนี้ทำให้คำอธิบายประกอบมีประสิทธิภาพน้อยกว่า XML อย่างเคร่งครัด
2833557

3

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

ฉันมีสถานการณ์ที่ฉันต้องการจำลอง GET, POST, PUT และ DELETE ในเว็บแอพ ฉันอยากจะมีคำอธิบายประกอบ "super" ที่เรียกว่า "HTTP_METHOD" ในเวลาต่อมาฉันก็รู้ว่ามันไม่สำคัญ ฉันต้องตกลงกับการใช้เขตข้อมูลที่ซ่อนอยู่ในรูปแบบ HTML เพื่อระบุ DELETE และ PUT (เนื่องจาก POST และ GET พร้อมใช้งานแล้ว)

บนฝั่งเซิร์ฟเวอร์ฉันมองหาพารามิเตอร์คำขอซ่อนด้วยชื่อ "_method" หากค่าคือ PUT หรือ DELETE ก็จะแทนที่วิธีการร้องขอ HTTP ที่เกี่ยวข้อง ต้องบอกว่ามันไม่สำคัญว่าฉันจะต้องเพิ่มหมายเหตุประกอบเพื่อให้งานเสร็จหรือไม่ คำอธิบายประกอบทั้งหมดดูเหมือนกัน แต่ได้รับการปฏิบัติต่างกันที่ฝั่งเซิร์ฟเวอร์

ดังนั้นในกรณีของคุณให้วางคันเพื่อขยายคำอธิบายประกอบ ปฏิบัติต่อพวกเขาในฐานะ 'เครื่องหมาย' พวกเขา "แสดง" ข้อมูลบางอย่างและไม่จำเป็นต้อง "จัดการ" ข้อมูลบางอย่าง


2

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


2

ไม่เคยคิดเรื่องนั้น แต่ ... ดูเหมือนว่าคุณพูดถูกไม่มีปัญหากับเครื่องมืออำนวยความสะดวกในการเพิ่มความคิดเห็น (อย่างน้อยฉันก็ไม่เห็นปัญหากับมัน)

เกี่ยวกับตัวอย่างของคุณด้วยคำอธิบายประกอบ'validator' - คุณสามารถใช้ประโยชน์จากวิธีการ'คำอธิบายประกอบแบบย่อ'ได้ คือคุณใช้คำอธิบายประกอบโดยเฉพาะกับอินเทอร์เฟซคำอธิบายประกอบทั้งหมด


ฉันอาจมาสายสามปีในการตอบคำถามนี้ แต่ฉันคิดว่ามันน่าสนใจเพราะฉันพบว่าตัวเองอยู่ในจุดเดียวกัน
mainas

1

ปัญหาเดียวกันฉันมี ไม่คุณไม่สามารถ ฉันทำ 'วินัย' ด้วยตัวเองเพื่อเขียนคุณสมบัติในหมายเหตุประกอบเพื่อเคารพมาตรฐานบางอย่างดังนั้นเมื่อคุณได้รับคำอธิบายประกอบคุณสามารถ 'สูดดม' สิ่งที่มีการเพิ่มความคิดเห็นแบบไหนโดยคุณสมบัติ

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