เปรียบเทียบโปรโตคอลใน Swift กับ Interface ใน Java


149

ฉันจะผ่าน iOS กวดวิชาจากหน้านักพัฒนาแอปเปิ้ล

ดูเหมือนว่าฉันprotocolและinterfaceเกือบจะมีฟังก์ชั่นเดียวกัน

  • มีความแตกต่างระหว่างสองคนนี้ไหม?

  • การใช้งานที่แตกต่างกันในโครงการ?

Updated

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


1
โปรโตคอลใน Swift และอินเตอร์เฟสใน Java เป็นแนวคิดเดียวกัน ดูที่นี่
Vivek Molkar

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

1
ต่อไปนี้เป็นจุดสำคัญในโลกแห่งความจริงเกี่ยวกับ Java interfaces - stackoverflow.com/a/41143492/294884 - นั่นจะเป็นกุญแจสำคัญสำหรับทุกคนที่สนใจกับ Swift ลองใช้ Java
Fattie

ในอีกทางหนึ่งมันเป็นที่น่าจดจำว่าทั้ง raison d'etreของ Swift นั้นมีไว้สำหรับ "การเขียนโปรแกรมเชิงโปรโตคอล" คุณทำทุกอย่างด้วย "ส่วนขยายโปรโตคอล" ใน Swift ubiquitously ตัวอย่างเช่นนี่เป็นปัญหาที่ละเอียดอ่อนเกี่ยวกับ Swift (เช่น: "เกี่ยวกับส่วนขยายโปรโตคอล") ซึ่งแสดงถึงปัญหาบางอย่าง
Fattie

2
ใน Swift แทนส่วนติดต่อชื่อโปรโตคอลจะถูกใช้เพราะในไฟล์ส่วนหัว Objective C (รายการซ้ำที่ไม่มีประโยชน์) จาก C จะถูกเรียกว่าส่วนต่อประสาน
Alex78191

คำตอบ:


117

โปรโตคอลพื้นฐานนั้นคล้ายกับอินเตอร์เฟสของ Java ยกเว้น:

  • โพรโทคอล Swift ยังสามารถระบุคุณสมบัติที่ต้องดำเนินการ (เช่นฟิลด์)
  • โปรโตคอล Swift จำเป็นต้องจัดการกับค่า / การอ้างอิงผ่านการใช้คำหลักกลายพันธุ์ (เนื่องจากโปรโตคอลสามารถนำมาใช้โดย structs และคลาส)
  • คุณสามารถรวมโปรโตคอลได้ทุกเมื่อด้วยคีย์เวิร์ดของโปรโตคอล <> ตัวอย่างเช่นการประกาศพารามิเตอร์ฟังก์ชันที่ต้องปฏิบัติตามโปรโตคอล A และ B เป็น:

.

func foo ( var1 : protocol<A, B> ){}

นี่คือความแตกต่างที่ชัดเจนในทันทีสำหรับนักพัฒนา Java (หรืออย่างน้อยที่สุดที่ฉันเคยเห็นมา)


13
" โปรโตคอล <> คำหลัก ": มันเจ๋งจริงๆ! ฉันคิดว่านี่คือสิ่งที่เรียกว่าประเภทจุดตัดในชุมชนทฤษฎีระบบชนิด ฉัน Java คุณสามารถมีประเภทประเภทนี้สำหรับพารามิเตอร์ประเภทที่มีหลายขอบเขต บทความนี้แนะนำการแนะนำพวกเขาเป็นภาษาจาวาเป็นประเภทเฟิร์สคลาสพร้อมด้วยไวยากรณ์เพื่อแสดงถึง
Lii

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

2
@rickster Java 8 ก็สามารถเพิ่มการนำไปใช้งานกับอินเทอร์เฟซได้โดยติดแท็กวิธีด้วยdefault คำสำคัญ ดูออราเคิลกวดวิชา
Basil Bourque

5
คำหลักโปรโตคอล <> ได้ถูกลบออกในความโปรดปรานของเครื่องหมายและ ดังนั้นคุณสามารถเขียน: ให้ c: A & B
Paul Robinson

2
ใน Swift แทนส่วนติดต่อชื่อโปรโตคอลจะถูกใช้เพราะในไฟล์ส่วนหัว Objective C (รายการซ้ำที่ไม่มีประโยชน์) จาก C จะถูกเรียกว่าส่วนต่อประสาน
Alex78191

33

การตอบสนองคำตอบของ @Thomas Schar โพรโทคอลเวทย์มนตร์ Swift มาจากส่วนขยาย

  • โปรโตคอล Swift สามารถรับการใช้งานผ่านส่วนขยาย (Swift
    2) อินเทอร์เฟซ Java 8 สามารถมีการใช้งานเริ่มต้นได้ แต่ไม่สามารถทำได้ "ย้อนหลัง"
  • ใน Swift คุณสามารถ "ย้อนกลับ" เพิ่มข้อกำหนดของโพรโทคอล (และ
    การนำไปปฏิบัติหากจำเป็น) ให้กับคลาสหรือโครงสร้างใด ๆ
  • โปรโตคอล Swift ไม่เป็นไปตามรูปแบบการปรับแต่งทั่วไป (เช่น <.. >) แต่เป็นแบบแผนประเภท (เช่นประเภทที่เกี่ยวข้อง) อาจทำให้เกิดความสับสนในช่วงเริ่มต้น แต่สามารถหลีกเลี่ยง
    "ตาบอดวงเล็บมุม" ในบางกรณี
  • Swift มีการจับคู่รูปแบบชนิดขั้นสูงทำให้สามารถระบุได้อย่างชัดเจนว่าข้อกำหนดและส่วนขยายของโปรโตคอลและส่วนขยายใดถูกนำไปใช้ มันอาจสร้างความสับสนเมื่อมาจาก Java แต่มีพลังงานมาก
  • โพรโทคอล swift สามารถสร้างขึ้นสำหรับคุณสมบัติ / พารามิเตอร์ (เช่น celebrator: โปรโตคอล)

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


7
โปรโตคอล Swift สามารถมีสมาชิกที่เป็นทางเลือกได้ซึ่งแตกต่างจากอินเตอร์เฟส Java
eyeApps LLC

4
จุดเล็ก ๆ ที่เกิดขึ้นในสวิฟท์คือไม่มีฟังก์ชั่นที่เป็นนามธรรม (ไร้สาระ) ดังนั้นคุณจึงไป "พิมพ์คุณลืมสิ่งนี้!" ... stackoverflow.com/a/24111430/294884
Fattie

@Fattie คุณสามารถใช้คีย์เวิร์ด "required" ในฟังก์ชั่นเพื่อระบุว่าต้องการการใช้คลาสย่อย ดังนั้นจริงๆเหมือนความไม่รู้เล็กน้อยกว่าจุดที่เกิดขึ้นจริง
เดิร์คเบสเตอร์

@DirkBester - ไชโย - รอคุณกำลังพูดถึง initializers อยู่หรือเปล่า?
Fattie

อีกครั้ง @DirkBester ฉันอาจมีความสับสน แต่ไม่สามารถใช้requiredก่อนหน้าที่ในโพรโทคอลคุณเพิ่งได้รับ'required' may only be used on 'init' declarations...
Fattie
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.