ความแตกต่างระหว่างอินเตอร์เฟส Java และโปรโตคอล Objective-C?


93

ฉันรู้จัก Java และตอนนี้ฉันเรียน Objective-C อะไรคือความแตกต่างระหว่างอินเตอร์เฟส Java และโปรโตคอล Objective-C

คำตอบ:


82

ก่อนอื่นให้ดูมุมมองทางประวัติศาสตร์เล็กน้อยในหัวข้อนี้จากหนึ่งในผู้สร้าง Java ถัดไป, วิกิพีเดียมีประโยชน์ในระดับปานกลางส่วนบนโปรโตคอล Objective-C โดยเฉพาะอย่างยิ่งโปรดเข้าใจว่า Objective-C สนับสนุนทั้งโปรโตคอลที่เป็นทางการ (ซึ่งประกาศอย่างชัดเจนด้วย@protocolคีย์เวิร์ดเทียบเท่ากับอินเทอร์เฟซ Java) และโปรโตคอลแบบไม่เป็นทางการ (เพียงหนึ่งวิธีหรือมากกว่าที่ใช้ในคลาสซึ่งสามารถค้นพบได้ผ่านการสะท้อนกลับ)

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

if ([myObject conformsToProtocol:@protocol(MyProtocol)]) {
    ...
}

หมายเหตุ: สถานะเอกสารของ Apple :

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

สำหรับ Objective-C 2.0 (ใน OS X 10.5 "Leopard" และ iOS) ตอนนี้โปรโตคอลที่เป็นทางการสามารถกำหนดวิธีการเสริมได้และคลาสจะเป็นไปตามโปรโตคอลตราบใดที่ใช้วิธีการที่จำเป็นทั้งหมด คุณสามารถใช้@required(ค่าเริ่มต้น) และ@optionalคำสำคัญเพื่อสลับว่าการประกาศวิธีการที่ตามมาจะต้องหรืออาจนำไปใช้เพื่อให้สอดคล้องกับโปรโตคอลหรือไม่ (ดูส่วนของคู่มือภาษาโปรแกรม Objective-C 2.0ของ Apple ที่กล่าวถึงวิธีโปรโตคอลเสริม )

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

if ([myObject respondsToSelector:@selector(fillArray:withObject:)]) {
    [myObject fillArray:anArray withObject:foo];
    ...
}

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


4
"ถ้าคุณใช้โปรโตคอลที่เป็นทางการ (คำศัพท์ Objective-C สำหรับ" ใช้งานอินเทอร์เฟซ ") คอมไพเลอร์จะส่งคำเตือนสำหรับวิธีการที่ไม่ได้ใช้งานเช่นเดียวกับที่คุณคาดหวังใน Java" Java จะแสดงข้อผิดพลาดในกรณีนี้ไม่ใช่คำเตือน
Raffi Khatchadourian

3
"ถ้าคลาส Objective-C ใช้วิธีการที่มีอยู่ในโปรโตคอลที่เป็นทางการจะมีการกล่าวว่า" สอดคล้อง "กับโปรโตคอลนั้นแม้ว่าอินเทอร์เฟซจะไม่ได้นำมาใช้อย่างชัดเจนก็ตามคุณสามารถทดสอบความสอดคล้องของโปรโตคอลในโค้ด (โดยใช้ -conformsToProtocol: ) เช่นนี้ "นี่คือ FALSE -conformsToProtocol:จะส่งคืน YES ก็ต่อเมื่อชั้นเรียนใช้โปรโตคอลอย่างชัดเจน คุณเคยลองหรือยัง?
user102008

2
คุณถูกต้อง-conformsToProtocol:แน่นอนว่าชั้นเรียน (หรือบรรพบุรุษ) ประกาศอย่างเป็นทางการว่าใช้โปรโตคอลหรือไม่ ไม่แน่ใจว่าฉันทำผิดอย่างไรขอบคุณสำหรับการแก้ไข!
Quinn Taylor

18

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

เช่น

วัตถุประสงค์ C:

@protocol MyProtocol
// Protocol definition
@end

id <MyProtocol> myProtocol;

 [myProtocol retain] // Compiler warning

Java:

public interface MyInterface {
// interface definition
}

MyInterface myInterface;

myInterface.toString();  // Works fine.

วัตถุประสงค์ C (คงที่):

@protocol MyProtocol <NSObject>
// Protocol definition
@end

id <MyProtocol> myProtocol;

[myProtocol retain] // No Warning

25
เพราะนี่คือ ID และ NSObject จะไม่เหมือนกัน ใน Java วัตถุรูทคือ Object ใน Objective-C, NSObject เป็นวัตถุราก แต่ไม่วัตถุราก หากคุณต้องการเข้าถึงเมธอด NSObject ทั้งหมด (เมธอดคลาสและโปรโตคอล) ให้ระบุสิ่งนี้อย่างชัดเจน: NSObject <MyProtocol> myProtocol; แทนที่จะเป็น: id <MyProtocol> ... เมื่อคุณใช้ id คุณกำลังพูดว่า: ฉันไม่สนใจเกี่ยวกับวัตถุมีเพียงโปรโตคอลซึ่งในกรณีของคุณไม่เป็นความจริง
Jason Coco
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.