ป้องกันในอินเทอร์เฟซ


111

เหตุใดวิธีการทั้งหมดจึงอยู่ในinterfaceคำจำกัดความโดยปริยายpublic? เหตุใดจึงไม่อนุญาตprotectedวิธีการ


22
คำถามที่ดีมาก เกือบทุกอย่างใน Java ฉันพบเหตุผลที่แท้จริงสำหรับตัวเลือกที่เลือก แต่สำหรับสิ่งนี้ฉันไม่ได้ทำ มันสมเหตุสมผลสำหรับฉันที่จะกำหนดวิธีการป้องกันในอินเทอร์เฟซซึ่งอนุญาตให้คลาสอื่นในแพ็คเกจเดียวกันใช้วิธีนี้กับอ็อบเจ็กต์การนำไปใช้โดยไม่ต้องเปิดเผยเมธอดนั้นซึ่งอาจไม่ได้หมายถึงการเรียกโดยบุคคลอื่นนอกเหนือจาก สมาชิกแพ็กเกจไปยังส่วนที่เหลือของโลก
Markus A.

4
@MarkusA. แต่อินเทอร์เฟซทำงานแบบสองทางกล่าวคือสามารถใช้งานได้โดยคลาสนอกแพ็กเกจปัจจุบัน (และอาจส่งผ่านเป็นอาร์กิวเมนต์ไปยังวิธีการภายในแพ็คเกจนี้) คลาสจากนอกแพ็กเกจปัจจุบันจะใช้วิธี "ป้องกัน" ของอินเทอร์เฟซสาธารณะบางส่วนได้อย่างไร
MartinStettner

8
@MartinStettner: มันจะไม่ นั่นจะเป็นประเด็น แพ็กเกจอาจมีคลาสที่ไม่เกี่ยวข้องหลายคลาสซึ่งใช้อินเทอร์เฟซและต้องการรับประกันกับโค้ดใด ๆ ที่ได้รับการอ้างอิงของประเภทอินเทอร์เฟซนั้นว่าจะทำงานในลักษณะหนึ่ง การรับประกันดังกล่าวสามารถทำได้ดีกว่ามากหากสามารถป้องกันไม่ให้โค้ดภายนอกอ้างว่าใช้อินเทอร์เฟซในขณะที่ประพฤติตัวขัดกับสัญญา
supercat

1
@MarkusA. คุณยกจุดที่ดีคุณควรจะทำได้ด้วยระบบโมดูลของ Java 9
Nir Alfasi

1
หากอินเทอร์เฟซมีprotectedเมธอดคลาสการใช้งานทั้งหมดจะถูกมองว่าเป็นประเภทย่อยของอินเทอร์เฟซ และคลาสเหล่านี้ทั้งหมดสามารถเข้าถึงวิธีการป้องกันได้ มันไม่ทำให้protectedคำหลักในวิธีการไร้ประโยชน์? ตราบเท่าที่เราไม่มีวิธีใด ๆ ในการ จำกัดผู้ที่ใช้งาน คำหลักที่มีการป้องกันอินเทอร์เฟซนี้ในวิธีการนั้นก็ไร้ประโยชน์ ช่วยแก้ให้ด้วยนะถ้าฉันผิด!
amarnath ทำร้าย

คำตอบ:


67

เนื่องจากอินเทอร์เฟซควรหมายถึง "สิ่งที่คุณสามารถเห็นได้จากภายนอกชั้นเรียน" มันไม่สมเหตุสมผลที่จะเพิ่มวิธีการที่ไม่ใช่สาธารณะ


16
แต่ทำไมไม่มีฟังก์ชั่นที่เฉพาะสมาชิกในแพ็กเกจเดียวกันกับอินเทอร์เฟซ "สามารถดูได้จากนอกคลาส"? ฉันมีกรณีการใช้งานหลายกรณีที่ฉันต้องการสิ่งนี้
Markus A.

5
@MarkusA. ฉันรู้ว่านี่มันสายไปแล้ว แต่คุณสามารถทำให้เต็มที่abstract classซึ่งก็คือทั้งหมดinterfaceและระบุการเข้าถึงที่คุณต้องการ ได้รับสิ่งนี้สูญเสียประโยชน์จากการใช้งานหลายอย่างที่interfaceได้รับใน Java แต่การสร้างสัญญาที่ปฏิบัติตามข้อ จำกัด ของแพ็คเกจอื่น ๆ โดยสุจริตจะไม่สามารถทดสอบได้และทำให้เกิดความสับสนเนื่องจากคุณจะไม่สามารถเข้าถึงวิธีการใช้งานของคุณเองนอกแพ็คเกจนั้นได้ .
pickypg

10
@pickypg แต่ถ้าคลาสที่จะใช้อินเทอร์เฟซนั้นขยายคลาสอื่นอยู่แล้วคุณจะไม่สามารถขยายคลาสอื่นได้ ฉันจะไม่รู้สึกสับสนสำหรับอินเทอร์เฟซที่ใช้ภายในแพ็คเกจเท่านั้น
Flamma

24
@Raveline, -1 สิ่งนี้ทำให้เกิดคำถาม "ทำไมอินเทอร์เฟซจึงควรหมายถึงสิ่งที่คุณเห็นจากภายนอกชั้นเรียน" Java 8 อนุญาตเนื้อหาเมธอดในอินเทอร์เฟซแล้วทำไมไม่อนุญาตให้ใช้เมธอดนามธรรมที่มีการป้องกันด้วย
Pacerier

8
ฉันมักจะอ่านคำอธิบายนี้ แต่ผิด IMHO อินเทอร์เฟซคือ "โปรโตคอลการแลกเปลี่ยนมาตรฐาน" ไม่ว่าจะพูดถึง OOP, API การสื่อสารหรือฮาร์ดแวร์ก็ตาม พอร์ต USB บนพีซีของฉันเป็นอินเทอร์เฟซสาธารณะอย่างชัดเจน แต่หมุดบนเมนบอร์ดของฉันซึ่งอยู่ด้านหลังเคสที่ล็อคคีย์ซึ่งให้การเข้าถึงพอร์ต USB เสริมนั้นเป็นอินเทอร์เฟซที่ "ป้องกัน" อย่างชัดเจน จากนั้นเราก็มีชิป BIOS ซึ่งเป็นอินเทอร์เฟซมาตรฐานเช่นกัน แต่ไม่เคยเปิดเผยต่อสาธารณะ แต่อย่างใดมีเพียงไม่กี่ บริษัท เท่านั้นที่ทราบรายละเอียดที่แน่นอนเป็นการส่วนตัว แน่นอนว่าอินเทอร์เฟซสามารถมองเห็นได้! ทำไมไม่อยู่ใน OOP?
Foo Bar

55

แม้ว่าเหตุผลที่ยกมาบ่อยๆคือ "อินเทอร์เฟซกำหนด API สาธารณะ" แต่ฉันคิดว่านั่นเป็นการทำให้เข้าใจง่ายเกินไป (และมัน "มีกลิ่น" ของตรรกะแบบวงกลมด้วย)

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

จริงๆแล้วฉันคิดว่าส่วนหนึ่งของการให้เหตุผลเบื้องหลังการทำให้สมาชิกของอินเทอร์เฟซเป็นสาธารณะโดยปริยายคือมันทำให้ภาษา Java ง่ายขึ้น :

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

  • สมาชิกอินเทอร์เฟซสาธารณะโดยปริยายทำให้ข้อกำหนดภาษาง่ายขึ้น ... และด้วยเหตุนี้งานสำหรับผู้เขียนคอมไพเลอร์ Java และผู้ที่ใช้ Reflection API

แนวความคิดที่ว่า "อินเทอร์เฟซกำหนด API สาธารณะ" เป็นผลมาจาก (หรือลักษณะเฉพาะ) ของการตัดสินใจออกแบบภาษาที่ง่ายขึ้น ... ไม่ใช่วิธีอื่น แต่ในความเป็นจริงความคิดทั้งสองแนวอาจพัฒนาควบคู่กันไปในความคิดของนักออกแบบ Java

ไม่ว่าในกรณีใดก็ตามการตอบสนองอย่างเป็นทางการต่อ RFE ในJDK-8179193ทำให้ชัดเจนว่าทีมออกแบบ Java ตัดสินใจ2ว่าการอนุญาตให้protectedใช้อินเทอร์เฟซจะเพิ่มความซับซ้อนเพื่อประโยชน์ที่แท้จริงเพียงเล็กน้อย รุ่งโรจน์เพื่อ @skomisa สำหรับการหาหลักฐาน

หลักฐานใน RFE ช่วยแก้ปัญหาได้ นั่นคือเหตุผลอย่างเป็นทางการว่าทำไมจึงไม่มีการเพิ่ม


1 - แน่นอนว่าโปรแกรมเมอร์มือฉมังไม่มีปัญหากับสิ่งเหล่านี้และอาจยินดีต้อนรับคุณสมบัติการควบคุมการเข้าถึงที่สมบูรณ์ยิ่งขึ้น แต่จะเกิดอะไรขึ้นเมื่อรหัสของพวกเขาถูกส่งไปให้คนอื่นรักษา?

2 - คุณอาจไม่เห็นด้วยกับการตัดสินใจของพวกเขาหรือการให้เหตุผลของพวกเขา แต่นั่นเป็นเรื่องที่น่าสงสัย


21

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

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

(สิ่งที่น่าเศร้านี้ไม่ได้เปลี่ยนความจริงที่ว่าฉันยังคงต้องทำให้โค้ดของฉันซับซ้อนเกินไปด้วยบทคัดย่อที่ไม่จำเป็น แต่ฉันตั้งใจจะส่งคำขอคุณสมบัติที่ Oracle)


ฉันเห็นด้วย 100% คลาสนามธรรมเป็นทางเลือกที่สมเหตุสมผลก่อนที่จะมีการแนะนำวิธีการเริ่มต้น อย่างไรก็ตามข้อ จำกัด ที่พวกเขาวางไว้ในการสืบทอดหลายอย่างหมายความว่าพวกเขาไม่สมบูรณ์แบบ การเชื่อมต่อกับวิธีการเริ่มต้นเป็นทางเลือกที่ดีกว่าในโลก a> = JDK 1.8 แต่เนื่องจากไม่สามารถจัดเก็บสถานะได้พวกเขาจึงอาศัยการกำหนดวิธีการนามธรรมอื่น ๆ เพื่อเปิดเผยสถานะซึ่งหมายความว่ารัฐถูกเปิดเผยต่อสาธารณะซึ่งไม่ใช่สิ่งที่เสมอไป คุณต้องการ.
Fr Jeremy Krieg

10

เนื่องจากอินเทอร์เฟซกำหนด API สาธารณะ สิ่งที่ได้รับการป้องกันคือรายละเอียดภายในซึ่งไม่ได้อยู่ในอินเทอร์เฟซ

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


5
คุณระบุว่า "เพราะอินเทอร์เฟซกำหนด API สาธารณะ" แล้วเหตุผลที่อินเทอร์เฟซควรกำหนดเฉพาะpublicAPI คืออะไร? มีความแตกต่างระหว่าง "รายละเอียดภายใน" กับ "รายละเอียดการใช้งาน" protectedใน Java ไม่ใช่รายละเอียดภายในอย่างแน่นอนเนื่องจากตอนนี้เป็นอินเทอร์เฟซสาธารณะที่เผยแพร่ให้ทุกคนที่สามารถคลาสย่อยได้ซึ่งโดยพื้นฐานแล้วทั่วโลก
Pacerier

1
ไม่เป็นความจริงอีกต่อไปด้วยวิธีการเริ่มต้นของ Java 8
Mario Rossi

@MarioRossi และไม่เป็นความจริงอีกต่อไปด้วยวิธีการอินเตอร์เฟสส่วนตัวของ Java 9
skomisa

7

อาจเป็นเพราะมันเป็นอินเทอร์เฟซกล่าวคือมีไว้เพื่อบอกลูกค้าว่าพวกเขาสามารถทำอะไรกับอินสแตนซ์ได้แทนที่จะบอกพวกเขาว่าพวกเขาทำอะไรไม่ได้


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

6

ฉันรู้สึกเป็นอย่างยิ่งว่าอินเทอร์เฟซควรอนุญาตวิธีการป้องกัน ใครบอกว่าทุกคนในโลกต้องมองเห็นอินเทอร์เฟซได้ ในประเด็นของคุณที่อาจสร้างความสับสนให้กับโปรแกรมเมอร์ "ธรรมดา" (อ่าน: ไร้ความสามารถ): OOP ส่วนใหญ่เกี่ยวกับการจัดโครงสร้างออบเจ็กต์คลาสแพ็คเกจ ฯลฯ อย่างเหมาะสมหากโปรแกรมเมอร์มีปัญหาในการทำทุกอย่างให้ถูกต้องเขามี ปัญหาที่ใหญ่กว่ามาก Java ถูกสร้างขึ้นสำหรับสิ่งประเภทนั้น


สิ่งนี้ไม่ตอบคำถาม
Stephen C

5

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

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

วิธีการป้องกันในอินเทอร์เฟซ: แชร์ข้ามแพ็คเกจ

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

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

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

วิธีนี้เราสามารถแบ่งปันวิธีการบางอย่างกับแพ็คเกจที่รู้จักกันดี

และนี่คือการตอบสนองต่อคำขอการปรับปรุงซึ่งปิดด้วยสถานะWon't fix:

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

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

ดังนั้นประเด็นที่น่าเชื่อถือจากรายงานข้อบกพร่องนั้นคือ:

  • สถานการณ์ปัจจุบันจะไม่เปลี่ยนแปลง อินเทอร์เฟซไม่น่าจะรองรับprotectedวิธีการได้
  • เหตุผลที่ไม่สนับสนุนprotectedวิธีการในอินเทอร์เฟซคือ " เพิ่มความซับซ้อนและกรณีพิเศษเพื่อให้ได้ผลตอบแทนที่แท้จริงเพียงเล็กน้อย "
  • เนื่องจาก Java 9 มีแนวทางอื่นสำหรับการเข้าถึงระดับแพ็กเกจสำหรับวิธีการ ใช้Java Platform Module System (JPMS)เพื่อ " ทำให้คลาสและเมธอดเป็นสาธารณะ แต่อยู่ในโมดูลที่มีคุณสมบัติในการส่งออกไปยังโมดูล" เพื่อน "ที่เฉพาะเจาะจงแทนที่จะส่งออกไปยังสาธารณะทั่วไป "

4

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


2

อินเทอร์เฟซหากคุณต้องการใช้สิ่งที่คุณอธิบายไว้ให้ใช้คลาสนามธรรมหรืออินเทอร์เฟซที่ซ้อนกัน

การคัดลอกจากCode Styleเกี่ยวกับตัวแปรอินเทอร์เฟซ แต่ยังคงใช้กับ method แม้ว่า:

ตัวแปรอินเทอร์เฟซเป็นแบบสาธารณะโดยปริยายเนื่องจากอินเทอร์เฟซมีไว้เพื่อจัดเตรียม Application Programming Interface (API) ที่โปรแกรมเมอร์ Java สามารถเข้าถึงได้โดยสมบูรณ์เพื่ออ้างอิงและนำไปใช้ในแอปพลิเคชันของตนเอง เนื่องจากอินเทอร์เฟซอาจถูกใช้ในแพ็กเกจ Java ที่แตกต่างจากของตนเองการเปิดเผยต่อสาธารณะจึงมั่นใจได้ว่าโค้ดโปรแกรมสามารถเข้าถึงตัวแปรได้

2

การประกาศprotectedอินเทอร์เฟซย่อยภายในเป็นแนวทางปฏิบัติที่ดี แต่ในทางเทคนิคคุณไม่สามารถประกาศเมธอดภายในของคุณได้เช่นเดียวกับอินเทอร์เฟซใน Java

แน่นอนคุณสามารถสร้างอินเทอร์เฟซอื่นสำหรับการใช้งานภายในซึ่งขยายอินเทอร์เฟซสาธารณะ:

package yourpackage;

public interface PublicInterface {

    public void doThing1();

    public void doThing2();

    public void doThing3();

}

package yourpackage;

interface InternalInterface extends PublicInterface {

    void doAnyInternalThing1();

    void doAnyInternalThing2();

}

คุณสามารถใช้InternalInterfaceอินเทอร์เฟซภายในแพ็กเกจได้ แต่คุณควรยอมรับประเภทย่อยของPublicInterface(ในวิธีการสาธารณะ):

package yourpackage;

public class SomeClass {

    public void someMethod(PublicInterface param) {
        if (param instanceof InternalInterface) {
            // run the optimized code
        } else {
            // run the general code
        }
    }

}

นอกแพ็กเกจผู้ใช้สามารถใช้ได้PublicInterfaceโดยไม่มีปัญหา

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


1
ผู้ใช้นอกแพ็กเกจก็สามารถใช้ได้YourPublicInterface.Internalเช่นกัน ทุกอย่างในอินเทอร์เฟซรวมถึงอินเทอร์เฟซที่ซ้อนกันเป็นสาธารณะไม่ว่าจะมีหรือไม่มีpublicคีย์เวิร์ดก็ตาม
Greg Roelofs

1

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

และแม้แต่สถานการณ์แพ็คเกจก็ไม่ใช่อินเทอร์เฟซที่เกี่ยวข้อง

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


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

0

เมธอดที่ได้รับการป้องกันสามารถเข้าถึงได้เสมอโดยคลาสย่อยเฉพาะในกรณีที่คลาสย่อยขยายคลาสฐาน

ในกรณีของอินเทอร์เฟซคลาสย่อยจะไม่ขยายอินเทอร์เฟซ มันใช้อินเทอร์เฟซ

วิธีการป้องกันสามารถเข้าถึงได้ผ่านการขยายและไม่สามารถใช้งานได้


คีย์เวิร์ดอะไรต่างกันก็ไม่สำคัญ
Alex78191

0

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

public interface MyInterface {
    public void publicMethod(); // needs to be public
}

public abstract class MyAbstractClass implements MyInterface {
    @Override
    public void publicMethod() {
        protectedMethod(); // you can call protected method here
        // do other stuff
    }
    protected abstract void protectedMethod(); // can be protected
}

public class MyClass extends MyAbstractClass {
    @Override
    protected void protectedMethod() {
        // implement protected method here, without exposing it as public
    }
}

2
แต่วิธีการส่วนตัวที่ไม่มีใครเห็นจะได้รับอนุญาตในอินเทอร์เฟซ
Alex78191

java มีวิธีการเริ่มต้นในอินเทอร์เฟซนั่นคืออินเทอร์เฟซเป็นไม้ค้ำยันเพื่อข้ามการสืบทอดคลาสนามธรรมหลาย ๆ คลาส อนุญาตให้มีการสืบทอดคลาสนามธรรมหลายรายการ ความขัดแย้งของวิธีการเริ่มต้นไม่ได้กลายเป็นปัญหา
Alex78191

คุณพูดถูก เนื่องจากวิธีการส่วนตัว Java 9 อนุญาตให้ใช้ในอินเทอร์เฟซ สิ่งเหล่านี้ไม่สามารถเป็นนามธรรมได้และถูกนำไปใช้และใช้ภายในอินเทอร์เฟซโดยส่วนใหญ่เป็นวิธีการเริ่มต้นหรือแบบคงที่ (หากเป็นแบบคงที่)
Stefanos Kargas

1
คำตอบนี้ไม่สนใจคำถามที่ถาม: ทำไมอินเทอร์เฟซจึงไม่สามารถป้องกันวิธีการได้? วิธีการที่ได้รับการป้องกันจะยังคง"เปิดเผยวิธีการสู่โลกภายนอก"และการอ้างว่า"วิธีการเหล่านี้เป็นสาธารณะโดยธรรมชาติ"นั้นเป็นเท็จ เป็นแบบสาธารณะเนื่องจากภาษาได้รับการออกแบบมาเช่นนั้น แต่อาจอนุญาตให้ใช้วิธีการป้องกันในอินเทอร์เฟซได้ OP กำลังถามว่าทำไม
skomisa
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.