2009-01-21 11 views
43

Objective-C'de id değişkenini bildirme arasındaki fark ne NSObject * bildiriyor?"id" ve "NSObject *" değişkenlerini bildirme arasındaki fark nedir?

+0

:

id testId; [testId performSelector:@selector(isKindOfClass:) withObject:[NSObject class] afterDelay:.5]; 

Ancak bu kod hatası No known instance method for selector "performSelector:withObject:afterDelay:" gösterecektir: NSObject 'ın kategori NSDelayedPerforming bu yöntemi beri

Yani, örneğin, bu kod, herhangi bir hata atmaz NSObject isa işaretçisi içeriyor, id değil. Http://stackoverflow.com/a/19634973/944634 –

cevap

51

id yazılan bir değişkenle, bilinen herhangi bir iletiyi gönderebilir ve derleyici şikayet etmeyecektir. NSObject * yazılan bir değişkenle, yalnızca NSObject tarafından bildirilen iletileri gönderebilirsiniz (herhangi bir alt sınıfın yöntemleri değil) veya başka bir uyarı üretecektir. Genel olarak, id istediğin şeydir.

Daha fazla açıklama: Tüm nesneler esas olarak id türündedir. Statik tip bildirme noktası derleyiciye "Bu nesnenin bu sınıfın bir üyesi olduğunu varsayalım" dır. Yani, eğer sınıfın bildirmediği bir mesaj gönderiyorsanız, derleyici size şunu söyleyecektir, "Bekle, bu nesne bu mesajı almamalı!" Ayrıca, iki sınıfın aynı ada sahip ancak farklı imzalara sahip yöntemleri varsa (yani, argüman veya döndürme türleri), değişken için bildirdiğiniz sınıf tarafından hangi yöntemi kastettiğinizi tahmin edebilirsiniz. Eğer id olarak beyan edildiyse, derleyici ellerini yukarı atar ve size "Tamam, burada yeterli bilgiye sahip değilim. Rastgele bir yöntem imzası seçiyorum" diyecektir. (Bu genellikle NSObject* bildirerek yardımcı olmaz, ama. Genellikle çakışma iki spesifik sınıfları arasında bulunur.)

+2

'a bir bakın. Büyük bir açıklama olsa da, "Genel olarak, id ne istediğinizi" tereddüt etmekteyim. Dinamik yazım nedeniyle "id" oldukça esnektir, ancak neredeyse hiçbir uyarı vermez, bu yüzden desteklenmeyen bir yöntem çağırırsanız, derleme zamanında yakalanabilecek bir çalışma zamanı sorunu olur. Statik yazım (MyClassName * vb. Ile)) Doğru kullanıldığında, özellikle Xcode'ta hata ayıklama yaparken (nesnenin daha akıllı bir özetini gösterebilir) veya yanlış yazılmış veya eksik seçicilerin yöntem çağrılarını yakalarken, hayatı daha kolay hale getirebilir. –

+0

Çizmek istediğim ayrım, özellikle id ve NSObject * arasında, genel olarak statik yazım değil. Kimlik kullanmak istediğinizde, NSObject olarak statik olarak yazmanızdan daha yaygındır. – Chuck

+0

@simpleBob: "Bilinen herhangi bir mesaj." – Chuck

17

id "bir nesneyi", NSObject * araçları "NSObject veya alt sınıflarından birinin bir örneği" anlamına gelir. Nesne-C'de NSObject s (şu anda Kakao'da buluşacağınız olanlar NSProxy, Protocol ve Class) nesneleri vardır. Bazı kodlar belirli bir sınıfın bir nesnesini beklerse, derleyicinin düzgün kullandığınızı kontrol etmesine yardımcı olduğunu bildirir. Eğer gerçekten "herhangi bir nesneyi" alabilirseniz - örneğin bir temsilci ilan ediyorsunuz ve tüm yöntemlerin respondsToSelector: çağrılarıyla gönderilmesini test edeceksiniz - bir id kullanabilirsiniz.

bir amacı, değişken bildirmek için başka bir yol gibi "id <NSObject>", yani "uygulayan herhangi bir nesne NSObject protokol. Tüm nesneler NSObject türetilir hedefi değildir-C, zaman sınırlı anlayış

+0

NSProxy ve Protokol sınıflarıdır. "Sınıf" bir sınıf değil, yalnızca sınıf nesnelerine işaretçilere başvurabilecek bir türdür. Onları bir araya getirme – user102008

+0

@ user102008: Bir nesneye mesaj gönderebilirsiniz, bu onu nesnenin dünyasında bir nesne haline getirir. –

+0

Evet, sınıf nesneleri nesnelerdir, ancak "Sınıf" adı verilen bir sınıf değildirler. – user102008

10

(aksine Tüm nesnelerin Nesne'den türetildiği Java. Teorik olarak diğer kök nesneler olabilirsiniz. NSObject türetilmiş nesnelerden herhangi birine uygulanabilir.

0

Başka bir fark eklemek istiyorum. id'a bir protokol eklediğinizde, Bu, NSObject * türünde olacağı anlamına gelmez, sadece herhangi bir clas olacağı anlamına gelir Bu protokole onay veriyor.

id<NSMutableCopying> testId; 
[testId performSelector:@selector(isKindOfClass:) withObject:[NSObject class] afterDelay:.5]; 
İlgili konular