Java arayüzleri ve Objective-C protokolleri arasındaki farklar?


93

Java'yı biliyorum ve şimdi Objective-C'yi öğreniyorum. Java arayüzleri ile Objective-C protokolleri arasındaki farklar tam olarak nedir?

Yanıtlar:


82

Öncelikle , Java'nın yaratıcılarından birinden konu hakkında biraz tarihsel bir bakış açısı . Daha sonra, Wikipedia'nın Objective-C protokolleri hakkında oldukça yararlı bir bölümü var . Özellikle, Objective-C'nin hem biçimsel protokolleri ( @protocolanahtar sözcükle açıkça bildirilen , bir Java arayüzünün eşdeğeri) hem de resmi olmayan protokolleri (yansıma yoluyla keşfedilebilen bir sınıf tarafından uygulanan yalnızca bir veya daha fazla yöntem ) desteklediğini anlayın .

Resmi bir protokol kullanırsanız ("arabirim uygulamak" için Objective-C terminolojisi), derleyici Java'da beklediğiniz gibi uygulanmayan yöntemler için uyarılar yayınlayacaktır. Java'nın aksine ( skaffman'ın bahsettiği gibi), bir Objective-C sınıfı resmi bir protokolde yer alan yöntemleri uygularsa, arabirimi açıkça benimsemese bile bu protokole "uygun" olduğu söylenir.Protokol uygunluğunu kodda ( -conformsToProtocol kullanarak ) şu şekilde test edebilirsiniz :

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

NOT: Apple'ın belgeleri şu şekildedir:

"Bu yöntem, yukarıda gösterildiği gibi, yalnızca başlık dosyalarındaki resmi bildirimler temelinde uygunluğu belirler. Protokolde bildirilen yöntemlerin gerçekten uygulanıp uygulanmadığını kontrol etmez - bu programcının sorumluluğundadır."

Objective-C 2.0'dan itibaren (OS X 10.5 "Leopard" ve iOS'ta), resmi protokoller artık isteğe bağlı yöntemleri tanımlayabilir ve bir sınıf, gerekli tüm yöntemleri uyguladığı sürece bir protokole uyar. Sen kullanabilirsiniz @required(varsayılan) ve @optionalizleyin yöntem bildirimleri olmadığını geçiş için anahtar kelimeler mutlaka ya edebilir uygulanacak protokole uyması için. (Apple'ın Objective-C 2.0 Programlama Dili kılavuzunun isteğe bağlı protokol yöntemlerini tartışan bölümüne bakın .)

İsteğe bağlı protokol yöntemleri, özellikle temsilcilerin ve dinleyicilerin uygulanması için geliştiricilere büyük esneklik sağlar . MouseInputAdapter gibi bir şeyi genişletmek (Java da tek kalıtım olduğu için can sıkıcı olabilir) ya da çok sayıda anlamsız, boş yöntem uygulamak yerine, bir protokol benimseyebilir ve yalnızca ilgilendiğiniz isteğe bağlı yöntemleri uygulayabilirsiniz. Bu desenle, arayan, yöntemin şu şekilde ( -respondsToSelector kullanarak ) çağrılmadan önce uygulanıp uygulanmadığını kontrol eder :

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

Yansımanın ek yükü bir sorun haline gelirse , boole sonucunu her zaman yeniden kullanım için önbelleğe alabilir , ancak erken optimize etme dürtüsüne direnebilirsiniz. :-)


4
"Resmi bir protokol kullanırsanız (" arabirim uygulamak "için Objective-C terminolojisi), derleyici, Java'da beklediğiniz gibi uygulanmayan yöntemler için uyarılar yayınlayacaktır." Java bu durumda bir uyarı değil bir hata verir.
Raffi Khatchadourian

3
"bir Objective-C sınıfı resmi bir protokolde yer alan yöntemleri uygularsa, arabirimi açıkça benimsemese bile bu protokole" uygun "olduğu söylenir. Kodda protokol uygunluğunu test edebilirsiniz (-conformsToProtocol kullanarak: ) böyle "Bu YANLIŞ. -conformsToProtocol:yalnızca sınıf açıkça protokolü benimserse EVET döndürür. Hiç denedin mi?
user102008

2
Haklısınız -conformsToProtocol:, gerçekten de sınıfın (veya bir atanın) resmi olarak protokolü benimsediğini beyan etmesini gerektirir. Bunu nasıl yanlış anladığımdan emin değilim, düzeltme için teşekkürler!
Quinn Taylor

18

Neredeyse aynılar. Bununla birlikte, beni yakalayan tek şey, nesnel bir C protokolünün NSObject'i de uyguladığını açıkça beyan etmediğiniz sürece, bu protokole yapılan referansların NSObject'in bildirdiği yöntemlere erişemeyeceğidir (yine de bir derleyici uyarısı olmadan). Java ile bir arayüze bir referansınız olabilir ve yine de üzerinde toString () vb.

Örneğin

Hedef 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.

Hedef C (sabit):

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

id <MyProtocol> myProtocol;

[myProtocol retain] // No Warning

25
Bunun nedeni id ve NSObject'in aynı olmamasıdır . Java'da kök nesne Object'tir. Objective-C olarak, NSObject bir kök nesne, ancak etmeyen kök nesnesi. Tüm NSObject yöntemlerine (protokollerin yanı sıra sınıf yöntemleri) erişmek istiyorsanız, bunu açıkça belirtin: NSObject <MyProtocol> myProtocol; Bunun yerine: id <MyProtocol> ... id'yi kullandığınızda şunu söylüyorsunuz: Nesne umurumda değil, sadece sizin durumunuzda doğru olmayan protokol.
Jason Coco
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.