Perbedaan antara antarmuka Java dan protokol Objective-C?

93

Saya tahu Java, dan sekarang saya belajar Objective-C. Apa sebenarnya perbedaan antara antarmuka Java dan protokol Objective-C?

Arne Evertsson
sumber

Jawaban:

82

Pertama, sedikit perspektif sejarah tentang topik tersebut , dari salah satu pencipta Jawa. Selanjutnya, Wikipedia memiliki bagian yang cukup membantu tentang protokol Objective-C . Secara khusus, pahami bahwa Objective-C mendukung kedua protokol formal (yang secara eksplisit dideklarasikan dengan @protocolkata kunci, setara dengan antarmuka Java) dan protokol informal (hanya satu atau lebih metode yang diterapkan oleh kelas, yang dapat ditemukan melalui refleksi).

Jika Anda mengadopsi protokol formal (terminologi Objective-C untuk "mengimplementasikan antarmuka") kompilator akan mengeluarkan peringatan untuk metode yang tidak diimplementasikan, seperti yang Anda harapkan di Java. Tidak seperti Java (seperti yang disebutkan skaffman ), jika kelas Objective-C mengimplementasikan metode yang terdapat dalam protokol formal, ia dikatakan "menyesuaikan" dengan protokol itu, bahkan jika antarmukanya tidak secara eksplisit mengadopsinya.Anda dapat menguji kesesuaian protokol dalam kode (menggunakan -conformsToProtocol :) seperti ini:

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

CATATAN: Dokumentasi Apple menyatakan:

"Metode ini menentukan kesesuaian hanya berdasarkan deklarasi formal dalam file header, seperti yang diilustrasikan di atas. Metode ini tidak memeriksa apakah metode yang dideklarasikan dalam protokol benar-benar diterapkan — itu tanggung jawab programmer."

Sejak Objective-C 2.0 (di OS X 10.5 "Leopard" dan iOS), protokol formal sekarang dapat mendefinisikan metode opsional , dan kelas sesuai dengan protokol selama mengimplementasikan semua metode yang diperlukan. Anda dapat menggunakan @required(default) dan @optionalkata kunci untuk beralih apakah deklarasi metode yang mengikuti harus atau dapat diimplementasikan agar sesuai dengan protokol. (Lihat bagian panduan Bahasa Pemrograman Objective-C 2.0 Apple yang membahas metode protokol opsional .)

Metode protokol opsional membuka banyak fleksibilitas bagi pengembang, terutama untuk mengimplementasikan delegasi dan pendengar . Alih-alih memperluas sesuatu seperti MouseInputAdapter (yang bisa mengganggu, karena Java juga merupakan pewarisan tunggal) atau menerapkan banyak metode kosong dan tidak berguna, Anda dapat mengadopsi protokol dan hanya mengimplementasikan metode opsional yang Anda pedulikan. Dengan pola ini, pemanggil memeriksa apakah metode diimplementasikan sebelum memanggilnya (menggunakan -respondsToSelector ) seperti ini:

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

Jika overhead refleksi menjadi masalah, Anda selalu dapat menyimpan hasil boolean ke dalam cache untuk digunakan kembali , tetapi menahan keinginan untuk mengoptimalkan sebelum waktunya. :-)

Quinn Taylor
sumber
4
"Jika Anda mengadopsi protokol formal (terminologi Objective-C untuk" mengimplementasikan antarmuka ") kompilator akan mengeluarkan peringatan untuk metode yang tidak diimplementasikan, seperti yang Anda harapkan di Java." Java akan mengeluarkan kesalahan dalam kasus ini, bukan peringatan.
Raffi Khatchadourian
3
"jika kelas Objective-C mengimplementasikan metode yang terdapat dalam protokol formal, ia dikatakan" menyesuaikan "dengan protokol itu, meskipun antarmukanya tidak secara eksplisit mengadopsinya. Anda dapat menguji kesesuaian protokol dalam kode (menggunakan -conformsToProtocol: ) seperti ini "Ini SALAH. -conformsToProtocol:hanya akan mengembalikan YA jika kelas secara eksplisit mengadopsi protokol. Apakah kamu sudah mencobanya?
user102008
2
Anda benar, -conformsToProtocol:memang mengharuskan kelas (atau leluhur) secara resmi menyatakan bahwa ia mengadopsi protokol. Tidak yakin bagaimana saya melakukan kesalahan ini, terima kasih atas koreksinya!
Quinn Taylor
18

Mereka hampir identik. Namun satu hal yang menarik perhatian saya, adalah bahwa kecuali Anda secara eksplisit menyatakan bahwa protokol C obyektif juga menerapkan NSObject, referensi ke protokol itu tidak mendapatkan akses ke metode yang dideklarasikan NSObject (tanpa peringatan compiler). Dengan java Anda dapat memiliki referensi ke sebuah antarmuka, dan masih memanggil toString () dll.

misalnya

Tujuan C:

@protocol MyProtocol
// Protocol definition
@end

id <MyProtocol> myProtocol;

 [myProtocol retain] // Compiler warning

Jawa:

public interface MyInterface {
// interface definition
}

MyInterface myInterface;

myInterface.toString();  // Works fine.

Tujuan C (tetap):

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

id <MyProtocol> myProtocol;

[myProtocol retain] // No Warning
Tom Jefferys
sumber
25
Ini karena id dan NSObject tidak sama . Di Java, objek root adalah Object. Di Objective-C, NSObject adalah objek root, tapi tidak dengan objek root. Jika Anda menginginkan akses ke semua metode NSObject (metode kelas serta protokol), nyatakan ini secara eksplisit: NSObject <MyProtocol> myProtocol; bukannya: id <MyProtocol> ... Ketika Anda menggunakan id Anda mengatakan: Saya tidak peduli tentang objek, hanya protokol, yang dalam kasus Anda tidak benar.
Jason Coco