Amaç-C - Objective-C

Amaç-C
Aile C
Tarafından tasarlandı Tom Love ve Brad Cox
İlk ortaya çıktı 1984 ; 37 yıl önce ( 1984 )
kararlı sürüm
2.0
Yazma disiplini statik , dinamik , zayıf
işletim sistemi Çapraz platform
Dosya adı uzantıları .h, .m, .mm, .M
İnternet sitesi geliştirici.apple.com
Başlıca uygulamalar
Clang , GCC
Tarafından etkilenmiş
C , Küçük konuşma
Etkilenen
Harika , Java , Nu , Objective-J , TOM , Swift

Objective-C bir olan genel amaçlı , nesne yönelimli programlama dili ekler Smalltalk tarzı mesajlaşma için C programlama dili. İlk olarak 1980'lerin başında Brad Cox ve Tom Love tarafından geliştirilmiş , NeXTSTEP işletim sistemi için NeXT tarafından seçilmiştir . Objective-C, 2014'te Swift'in piyasaya sürülmesine kadar Apple tarafından macOS (NeXTSTEP'den türemiştir) ve iOS uygulamalarının ilgili uygulama programlama arabirimlerini (API'ler), Cocoa ve Cocoa Touch'ı kullanarak geliştirmek için desteklenen standart programlama diliydi .

Apple dışındaki işletim sistemleri için geliştirilen veya Apple'ın API'lerine bağımlı olmayan Objective-C programları da GNU GCC veya LLVM / Clang tarafından desteklenen herhangi bir platform için derlenebilir .

Objective-C kaynak kodu 'mesajlaşma/uygulama' program dosyaları genellikle .m dosya adı uzantılarına sahipken, Objective-C 'başlık/arayüz' dosyaları C başlık dosyalarıyla aynı .h uzantılarına sahiptir . Objective-C++ dosyaları .mm dosya uzantısıyla belirtilir.

Tarih

Objective-C, öncelikle Brad Cox ve Tom Love tarafından 1980'lerin başında, Productivity Products International (PPI) şirketlerinde oluşturuldu .

Onların şirket yaratılmasına kadar Öncü, hem tanıtıldı olmuştu Smalltalk ederken de ITT Corporation, 1981 yılında 'ın Programlama Teknolojisi Merkezi'nde izleri o zaman etrafında için geri Objective-C ile ilgili en erken çalışması. Cox, yazılım tasarımı ve programlamasında gerçek yeniden kullanılabilirlik sorunlarıyla ilgilendi . Smalltalk gibi bir dilin, ITT'deki sistem geliştiricileri için geliştirme ortamları oluşturmada çok değerli olacağını fark etti. Ancak, o ve Tom Love, ITT'nin telekom mühendisliği ortamında C ile geriye dönük uyumluluğun kritik derecede önemli olduğunu da fark ettiler.

Cox , Smalltalk'ın bazı yeteneklerini eklemek için C için bir ön işlemci yazmaya başladı . Kısa süre sonra, C diline yönelik, Nesne Yönelimli Ön Derleyici için "OOPC" adını verdiği nesne yönelimli bir uzantının çalışan bir uygulamasına sahipti . Love, 1982'de Schlumberger Research tarafından işe alındı ​​ve Smalltalk-80'in ilk ticari kopyasını edinme fırsatı buldu, bu da beyin çocuklarının gelişimini daha da etkiledi. Gerçek ilerleme kaydedilebileceğini göstermek için Cox, değiştirilebilir yazılım bileşenlerinin gerçekten mevcut araçlarda yalnızca birkaç pratik değişiklik gerektirdiğini gösterdi . Spesifik olarak, nesneleri esnek bir şekilde desteklemeleri, kullanılabilir bir kitaplık seti ile birlikte gelmeleri ve kodun (ve kodun ihtiyaç duyduğu tüm kaynakların) tek bir platformlar arası formatta paketlenmesine izin vermeleri gerekiyordu.

Love ve Cox sonunda ürünlerini ticarileştirmek için bir Objective-C derleyicisini sınıf kitaplıklarıyla birleştiren PPI'yi oluşturdu. 1986'da Cox, Objective-C'nin ana tanımını Object-Oriented Programming, An Evolutionary Approach kitabında orijinal haliyle yayınladı . Yeniden kullanılabilirlik sorununun Objective-C'nin sağladığından daha fazlası olduğunu belirtmekte dikkatli olmasına rağmen, dil genellikle diğer dillerle özellik için özellik karşılaştırıldı.

NeXT aracılığıyla popülerleşme

1988'de NeXT , StepStone'dan (PPI'nin yeni adı, Objective-C ticari markasının sahibi) Objective-C'yi lisansladı ve GCC derleyicisini Objective-C'yi destekleyecek şekilde genişletti . NeXT , NeXTSTEP kullanıcı arayüzü ve Arayüz Oluşturucu'nun dayandığı AppKit ve Foundation Kit kitaplıklarını geliştirdi . NeXT iş istasyonları piyasada büyük bir etki yaratmayı başaramamış olsa da, araçlar sektörde geniş çapta övgüyle karşılandı. Bu, NeXT'nin donanım üretimini bırakmasına ve yazılım araçlarına odaklanmasına ve NeXTSTEP'i (ve OPENSTEP'i) özel programlama için bir platform olarak satmasına neden oldu.

GPL şartlarını aşmak için , NeXT başlangıçta Objective-C ön ucunu ayrı olarak göndermeyi ve kullanıcının derleyici yürütülebilir dosyasını üretmek için GCC ile bağlamasına izin vermeyi amaçlamıştı. Başlangıçta Richard M. Stallman tarafından kabul edilmiş olsa da , bu plan Stallman'ın GNU'nun avukatlarına danıştıktan sonra reddedildi ve NeXT, Objective-C'yi GCC'nin bir parçası yapmayı kabul etti.

GCC'yi genişletme çalışmaları , StepStone'dan NeXT'ye katılan Steve Naroff tarafından yönetildi. Derleyici değişiklikleri, GPL lisans koşullarına göre kullanıma sunuldu , ancak çalışma zamanı kitaplıkları, açık kaynak katkısını genel halk için kullanılamaz hale getirdi. Bu, diğer tarafların bu tür çalışma zamanı kitaplıklarını açık kaynak lisansı altında geliştirmesine yol açtı. Daha sonra Steve Naroff, Clang için Objective-C ön ucunu oluşturmak için Apple'da çalışmaya baş katkıda bulundu .

GNU projesi onun özgür yazılım uygulaması üzerinde çalışmaya başladı Kakao adında, GNUstep'in dayalı OpenStep'in standardı. Dennis Glatting, ilk GNU Objective-C çalışma zamanını 1992'de yazdı. 1993'ten beri kullanımda olan GNU Objective-C çalışma zamanı, Kresten Krab Thorup tarafından Danimarka'da bir üniversite öğrencisiyken geliştirilmiş olanıdır . Thorup ayrıca 1993'ten 1996'ya kadar NeXT'de çalıştı.

Apple geliştirme ve Swift

1996'da NeXT'yi satın aldıktan sonra Apple Computer , OpenStep'i o zamanlar yeni olan işletim sistemi Mac OS X'te kullandı . Bu, NeXT'nin Objective-C tabanlı geliştirici aracı Project Builder olan Objective-C'yi ve onun arayüz tasarım aracı olan Interface Builder'ı içeriyordu . Her ikisi de daha sonra tek bir uygulamada birleştirildi, Xcode . Apple'ın mevcut Cocoa API'sinin çoğu, OpenStep arabirim nesnelerine dayanmaktadır ve aktif geliştirme için kullanılan en önemli Objective-C ortamıdır.

At WWDC 2014 Apple yeni bir dil, tanıtılan Swift "C olmaksızın Objective-C" olarak karakterize edildi.

Sözdizimi

Objective-C, C'nin üzerindeki ince bir katmandır ve C'nin "katı bir üst kümesidir ", yani herhangi bir C programını bir Objective-C derleyicisiyle derlemek ve bir Objective-C sınıfına C dil kodunu serbestçe dahil etmek mümkündür.

Objective-C, nesne sözdizimini Smalltalk'tan türetir . Nesne yönelimli olmayan işlemler için tüm sözdizimi (ilkel değişkenler, ön işleme, ifadeler, işlev bildirimleri ve işlev çağrıları dahil) C'ninkilerle aynıdır, nesne yönelimli özelliklerin sözdizimi ise Smalltalk- tarzı mesajlaşma

Mesajlar

Nesne yönelimli programlamanın Objective-C modeli, nesne örneklerine ileti aktarımına dayanır . Objective-C'de bir yöntem çağrılmaz ; biri mesaj atar . Bu, C++ tarafından kullanılan Simula tarzı programlama modelinden farklıdır . Bu iki kavram arasındaki fark, yöntemin veya mesaj adının başvurduğu kodun nasıl yürütüldüğüdür. Simula stili bir dilde, yöntem adı çoğu durumda derleyici tarafından hedef sınıftaki bir kod bölümüne bağlıdır . Gelen Smaltalk ve amaç-C, bir mesajın, hedef alıcı nesnesinin kendisi mesaj yorumlanması ile, çalışma anında çözümlenir. Bir yöntem, bir seçici veya SEL tarafından tanımlanır - her mesaj adı için benzersiz bir tanımlayıcı, genellikle adını temsil eden NUL ile sonlandırılmış bir dize - ve onu uygulayan bir C yöntemi işaretçisine çözümlenir : bir IMP . Bunun bir sonucu, mesaj iletme sisteminin tip denetimine sahip olmamasıdır. İletinin yönlendirildiği nesnenin - alıcının - bir mesaja yanıt vermesi garanti edilmez ve vermezse bir istisna oluşturur.

Obj işaretçisinin işaret ettiği nesneye mesaj yöntemini göndermek, C++ ' da aşağıdaki kodu gerektirir :

obj->method(argument);

Objective-C'de bu şu şekilde yazılır:

[obj method:argument];

"Yöntem" çağrısı, derleyici tarafından objc_msgSend(id self, SEL op, ...) çalışma zamanı işlevleri ailesine çevrilir . Farklı uygulamalar, super gibi modern eklemeleri işler . GNU ailelerinde bu işlev objc_msg_sendv olarak adlandırılır , ancak objc_msg_lookup altındaki modern bir arama sistemi lehine kullanımdan kaldırılmıştır .

Her iki programlama stilinin de güçlü ve zayıf yönleri vardır. Simula ( C++ ) stilinde nesne yönelimli programlama , mümkün olduğunda derleme zamanı bağlama kullanarak çoklu kalıtım ve daha hızlı yürütmeye izin verir , ancak varsayılan olarak dinamik bağlamayı desteklemez . Ayrıca, soyut olmadıkça tüm yöntemleri karşılık gelen bir uygulamaya sahip olmaya zorlar . Objective-C'de kullanılan Smalltalk tarzı programlama, çalışma zamanında uygulanmasına çözümlenen yöntem ile mesajların uygulanmamasına izin verir. Örneğin, çalışma zamanı hataları üretme korkusu olmadan yalnızca bazılarının yanıt vermesinin bekleneceği bir nesne koleksiyonuna bir mesaj gönderilebilir. İleti geçişi ayrıca derleme zamanında bir nesnenin tanımlanmasını gerektirmez. Yöntemin türetilmiş nesnede çağrılması için hala bir uygulama gereklidir. ( Dinamik (geç) bağlamanın daha fazla avantajı için aşağıdaki dinamik yazma bölümüne bakın.)

Arayüzler ve uygulamalar

Objective-C, bir sınıfın arayüzünün ve uygulamasının ayrı olarak bildirilen kod bloklarında olmasını gerektirir. Kural olarak, geliştiriciler arayüzü bir başlık dosyasına ve uygulamayı bir kod dosyasına yerleştirir. Normalde .h eki olan başlık dosyaları C başlık dosyalarına benzerken, normalde .m eki olan uygulama (yöntem) dosyaları C kod dosyalarına çok benzer olabilir.

Arayüz

Bu, C++ veya Python gibi diğer nesne yönelimli dillerde kullanılan sınıf bildirimlerine benzer.

Bir sınıfın arayüzü genellikle bir başlık dosyasında tanımlanır. Genel bir kural, başlık dosyasını sınıfın adından sonra adlandırmaktır, örneğin Ball.h , Ball sınıfının arabirimini içerir .

Bir arayüz bildirimi şu şekildedir:

@interface classname : superclassname {
  // instance variables
}
+ classMethod1;
+ (return_type)classMethod2;
+ (return_type)classMethod3:(param1_type)param1_varName;

- (return_type)instanceMethod1With1Parameter:(param1_type)param1_varName;
- (return_type)instanceMethod2With2Parameters:(param1_type)param1_varName
                              param2_callName:(param2_type)param2_varName;
@end

Yukarıdakilerde, artı işaretleri, sınıf yöntemlerini veya sınıfın kendisinde (bir örnekte değil) çağrılabilen yöntemleri belirtir ve eksi işaretleri , yalnızca sınıfın belirli bir örneğinde çağrılabilen örnek yöntemlerini belirtir . Sınıf yöntemlerinin ayrıca örnek değişkenlere erişimi yoktur .

Yukarıdaki kod kabaca aşağıdaki C++ arayüzüne eşdeğerdir :

class classname : public superclassname {
protected:
  // instance variables

public:
  // Class (static) functions
  static void *classMethod1();
  static return_type classMethod2();
  static return_type classMethod3(param1_type param1_varName);

  // Instance (member) functions
  return_type instanceMethod1With1Parameter(param1_type param1_varName);
  return_type
  instanceMethod2With2Parameters(param1_type param1_varName,
                                 param2_type param2_varName = default);
};

Not bu instanceMethod2With2Parameters: param2_callName: C / C doğrudan eşdeğer ++ var olduğu için bağımsız değişken ifadeler ile seçici bölümlerinin serpiştirme gösterir.

Dönüş türleri herhangi bir standart C türü, genel bir Objective-C nesnesine yönelik bir işaretçi, NSArray *, NSImage * veya NSString * gibi belirli bir nesne türüne yönelik bir işaretçi veya yöntemin ait olduğu sınıfa yönelik bir işaretçi olabilir. (örnek türü). Varsayılan dönüş türü, genel Objective-C türü id'dir .

Yöntem bağımsız değişkenleri, yöntem adının parçası olan bağımsız değişkeni etiketleyen bir adla başlar, ardından iki nokta üst üste işareti ve ardından parantez içinde beklenen bağımsız değişken türü ve bağımsız değişken adı gelir. Etiket atlanabilir.

- (void)setRangeStart:(int)start end:(int)end;
- (void)importDocumentWithName:(NSString *)name
      withSpecifiedPreferences:(Preferences *)prefs
                    beforePage:(int)insertPage;

Arayüz tanımının bir türevi, birinin mevcut sınıflara yöntemler eklemesine izin veren kategoridir .

uygulama

Arabirim, yöntemlerin kendisini değil, yalnızca sınıf arabirimini bildirir: gerçek kod, uygulama dosyasına yazılır. Uygulama (yöntem) dosyaları normalde .mbaşlangıçta "mesajlar" anlamına gelen dosya uzantısına sahiptir.

@implementation classname
+ (return_type)classMethod {
  // implementation
}
- (return_type)instanceMethod {
  // implementation
}
@end

Yöntemler, arayüz bildirimleri kullanılarak yazılır. Objective-C ve C'yi karşılaştırma:

- (int)method:(int)i {
  return [self square_root:i];
}
int function(int i) {
  return square_root(i);
}

Sözdizimi , argümanların sahte adlandırılmasına izin verir .

- (void)changeColorToRed:(float)red green:(float)green blue:(float)blue {
  //... Implementation ...
}

// Called like so:
[myColor changeColorToRed:5.0 green:2.0 blue:6.0];

Bir yöntemin dahili temsilleri, Objective-C'nin farklı uygulamaları arasında farklılık gösterir. myColor, Color sınıfındaysa , örnek yöntemi -changeColorToRed:green:blue: dahili olarak _i_Color_changeColorToRed_green_blue olarak etiketlenebilir . İ çizgi değiştirilmiştir sonra sınıf ve yöntem, ekteki isim ve iki nokta üst üste olan, bir örnek yöntemi bakınız etmektir. Parametrelerin sırası yöntem adının bir parçası olduğundan, doğru adlandırılmış parametrelerde olduğu gibi kodlama stiline veya ifadeye uyacak şekilde değiştirilemez.

Ancak, işlevin dahili adları nadiren doğrudan kullanılır. Genellikle mesajlar, Objective-C çalışma zamanı kitaplığında tanımlanan işlev çağrılarına dönüştürülür. Alıcının sınıfının (mesajı gönderen nesne) çalışma zamanına kadar bilinmesi gerekmediğinden, bağlantı zamanında hangi yöntemin çağrılacağı mutlaka bilinmez.

örnekleme

Objective-C sınıfı yazıldığında, somutlaştırılabilir. Bu, önce sınıfın başlatılmamış bir örneğini (bir nesne) tahsis ederek ve ardından onu başlatarak yapılır. Her iki adım da tamamlanana kadar bir nesne tam olarak işlevsel değildir. Bu adımlar bir kod satırı ile gerçekleştirilmelidir, böylece hiçbir zaman başlatmadan geçmemiş tahsis edilmiş bir nesne olmaz (ve -initçağrıldığından farklı bir nesne döndürebileceğinden ara sonucu saklamak akıllıca değildir ).

Varsayılan, parametresiz başlatıcı ile örnekleme:

MyObject *foo = [[MyObject alloc] init];

Özel bir başlatıcı ile örnekleme:

MyObject *foo = [[MyObject alloc] initWithString:myString];

Özel başlatmanın gerçekleştirilmediği durumda, genellikle alloc-init mesajları yerine "yeni" yöntem kullanılabilir:

MyObject *foo = [MyObject new];

Ayrıca, bazı sınıflar, sınıf yöntemi başlatıcılarını uygular. Gibi +new, birleştirir +allocve -init, ancak aksine +new, otomatik olarak yayınlanan bir örnek döndürürler. Bazı sınıf yöntemi başlatıcıları parametreleri alır:

MyObject *foo = [MyObject object];
MyObject *bar = [MyObject objectWithString:@"Wikipedia :)"];

Alloc bir nesne için tüm örnek değişkenleri tutmak için mesaj ayırır yeterli bellek, sıfır değerleri için tüm örnek değişkenleri ayarlar ve sınıfının bir örneğine bellek döner; başlatma sırasında hiçbir noktada bellek, üst sınıfın bir örneği değildir.

İnit mesajı seti makyaj oluşturulduktan sonra örneğinin gerçekleştirir. İnit aşağıdaki gibi yöntem genellikle yazılır:

- (id)init {
    self = [super init];
    if (self) {
        // perform initialization of object here
    }
    return self;
}

Yukarıdaki örnekte, iddönüş türüne dikkat edin . Bu tür, Objective-C'de "herhangi bir nesneye işaretçi" anlamına gelir ( Dinamik yazma bölümüne bakın).

Başlatıcı deseni, init yöntemi başlatma işlemini gerçekleştirmeden önce nesnenin üst sınıfı tarafından düzgün şekilde başlatıldığından emin olmak için kullanılır. Aşağıdaki eylemleri gerçekleştirir:

  1. self = [süper init]
    Üst sınıf örneğe bir gönderir init mesajı ve sonucu atar öz (mevcut nesnenin işaretçisi).
  2. eğer (kendi)
    Herhangi bir başlatma gerçekleştirmeden önce döndürülen nesne işaretçisinin geçerli olup olmadığını kontrol eder.
  3. kendine dön
    Arayana self değerini döndürür.

Geçerli olmayan bir nesne işaretçisi nil değerine sahiptir ; "if" gibi koşullu ifadeler nil'e bir boş gösterici gibi davranır, bu nedenle [super init] nil döndürürse başlatma kodu yürütülmez. Başlatmada bir hata varsa, init yöntemi, kendine bir "serbest bırakma" mesajı göndermek de dahil olmak üzere gerekli tüm temizleme işlemlerini gerçekleştirmeli ve başlatmanın başarısız olduğunu belirtmek için nil döndürmelidir . Bu tür hatalar için herhangi bir kontrol, yalnızca nesneyi yok etmenin doğru şekilde yapılmasını sağlamak için üst sınıf başlatma çağrısı yapıldıktan sonra gerçekleştirilmelidir.

Bir sınıfın birden fazla başlatma yöntemi varsa, bunlardan yalnızca birinin ("belirlenmiş başlatıcı") bu modeli izlemesi gerekir; diğerleri, üst sınıf başlatıcısı yerine belirlenmiş başlatıcıyı çağırmalıdır.

protokoller

Diğer programlama dillerinde bunlara "arayüzler" denir.

Objective-C, NeXT'de , protokollerin tanıtılması yoluyla uygulama değil, belirtimin çoklu kalıtımı kavramını tanıtmak için genişletildi . Bu, C++ 'da soyut çoklu kalıtsal temel sınıf olarak veya bir "arayüz" olarak (Java ve C#' da olduğu gibi) elde edilebilen bir modeldir . Objective-C, resmi olmayan protokoller olarak adlandırılan geçici protokolleri ve resmi protokoller adı verilen derleyici tarafından uygulanan protokolleri kullanır .

Gayri resmi bir protokol, bir sınıfın uygulamayı seçebileceği yöntemlerin bir listesidir. Dilde varlığı olmadığı için belgelerde belirtilmiştir. Resmi olmayan protokoller, NSObject üzerinde bir kategori olarak uygulanır (aşağıya bakın) ve genellikle isteğe bağlı yöntemleri içerir; bunlar, uygulandığında bir sınıfın davranışını değiştirebilir. Örneğin, bir metin alanı sınıfı , kullanıcı tarafından yazılan metnin otomatik olarak tamamlanmasını gerçekleştirmek için isteğe bağlı bir yöntemle gayri resmi bir protokol uygulayan bir temsilciye sahip olabilir . Metin alanı, temsilcinin bu yöntemi ( yansıma yoluyla ) uygulayıp uygulamadığını keşfeder ve eğer öyleyse, otomatik tamamlama özelliğini desteklemek için temsilcinin yöntemini çağırır.

Resmi bir protokol, Java, C# ve Ada 2005'teki bir arayüze benzer . Herhangi bir sınıfın uygulamak için kendisini ilan edebileceği yöntemlerin bir listesidir. Objective-C'nin 2.0'dan önceki sürümleri, bir sınıfın, benimsediğini beyan ettiği bir protokoldeki tüm yöntemleri uygulamasını gerektiriyordu; eğer sınıf, bildirdiği protokollerdeki her yöntemi uygulamazsa, derleyici bir hata yayacaktır. Objective-C 2.0, isteğe bağlı bir protokolde belirli yöntemleri işaretlemek için destek ekledi ve derleyici isteğe bağlı yöntemlerin uygulanmasını zorlamaz.

Bu protokolün kendisine uyduğunun söylenebilmesi için bir sınıfın bildirilmesi gerekir. Bu, çalışma zamanında algılanabilir. Resmi protokoller herhangi bir uygulama sağlayamaz; sadece arayanlara protokole uyan sınıfların uygulamalar sağlayacağına dair güvence verirler. NeXT/Apple kitaplığında, protokoller, uzak bir sistemde çalışan bir nesnenin yeteneklerini temsil etmek için Distributed Objects sistemi tarafından sıklıkla kullanılır.

sözdizimi

@protocol NSLocking
- (void)lock;
- (void)unlock;
@end

soyut bir kilitleme fikri olduğunu belirtir. Protokolün uygulandığını sınıf tanımında belirterek,

@interface NSLock : NSObject <NSLocking>
// ...
@end

NSLock örnekleri, iki örnek yöntemi için bir uygulama sağlayacaklarını iddia eder.

Dinamik yazma

Smalltalk gibi Objective-C de dinamik yazmayı kullanabilir : bir nesneye arayüzünde belirtilmeyen bir mesaj gönderilebilir. Bu, bir nesnenin bir mesajı "yakalamasına" ve mesajı, mesaja uygun şekilde yanıt verebilecek farklı bir nesneye göndermesine veya aynı şekilde mesajı başka bir nesneye göndermesine izin verdiğinden, esnekliğin artmasını sağlayabilir. Bu davranış, ileti iletme veya yetkilendirme olarak bilinir (aşağıya bakın). Alternatif olarak, mesajın iletilememesi durumunda bir hata işleyici kullanılabilir. Bir nesne bir ileti iletmezse, yanıt vermezse veya bir hatayı işlemezse, sistem bir çalışma zamanı istisnası oluşturur. Mesajlar nil'e (boş nesne işaretçisi) gönderilirse, derleyici seçeneklerine bağlı olarak sessizce yoksayılır veya genel bir istisna oluşturur.

Değişkenlere isteğe bağlı olarak statik yazma bilgisi de eklenebilir. Bu bilgi daha sonra derleme zamanında kontrol edilir. Aşağıdaki dört ifadede, giderek daha spesifik tür bilgileri sağlanmaktadır. İfadeler çalışma zamanında eşdeğerdir, ancak ek bilgiler, iletilen argüman belirtilen türle eşleşmediğinde derleyicinin programcıyı uyarmasına izin verir.

- (void)setMyValue:(id)foo;

Yukarıdaki açıklamada, foo herhangi bir sınıftan olabilir.

- (void)setMyValue:(id<NSCopying>)foo;

Yukarıdaki açıklamada foo , NSCopyingprotokole uyan herhangi bir sınıfın bir örneği olabilir .

- (void)setMyValue:(NSNumber *)foo;

Yukarıdaki ifadede foo , NSNumber sınıfının bir örneği olmalıdır .

- (void)setMyValue:(NSNumber<NSCopying> *)foo;

Yukarıdaki açıklamada foo , NSNumber sınıfının bir örneği olmalı ve NSCopyingprotokole uygun olmalıdır .

Objective-C'de tüm nesneler işaretçiler olarak temsil edilir ve statik başlatmaya izin verilmez. En basit nesne, id ( objc_obj * ) öğesinin işaret ettiği ve yalnızca sınıfını tanımlayan bir isa işaretçisine sahip olan türdür . Değerler ve yapılar gibi C'den diğer türler, nesne sisteminin bir parçası olmadıkları için değişmez. Bu karar, yapıların ve sınıfların birleştiği C++ nesne modelinden farklıdır.

Yönlendirme

Objective-C, yanıt vermeyebilecek bir nesneye mesaj gönderilmesine izin verir. Mesajı yanıtlamak veya basitçe bırakmak yerine, bir nesne mesajı yanıt verebilecek bir nesneye iletebilir. Yönlendirme , gözlemci deseni veya vekil desen gibi belirli tasarım desenlerinin uygulanmasını basitleştirmek için kullanılabilir .

Objective-C çalışma zamanı, Object içindeki bir çift yöntemi belirtir.

  • yönlendirme yöntemleri:
    - (retval_t)forward:(SEL)sel args:(arglist_t)args; // with GCC
    - (id)forward:(SEL)sel args:(marg_list)args; // with NeXT/Apple systems
    
  • eylem yöntemleri:
    - (retval_t)performv:(SEL)sel args:(arglist_t)args; // with GCC
    - (id)performv:(SEL)sel args:(marg_list)args; // with NeXT/Apple systems
    

İletmeyi uygulamak isteyen bir nesnenin, iletme davranışını tanımlamak için yalnızca iletme yöntemini yeni bir yöntemle geçersiz kılması gerekir. performv:: eylem yönteminin geçersiz kılınması gerekmez, çünkü bu yöntem yalnızca seçiciye ve bağımsız değişkenlere dayalı bir eylem gerçekleştirir. SELObjective-C'deki mesajların türü olan türe dikkat edin .

Not: Objective-C'nin yaygın olarak kullanılan çerçeveleri olan OpenStep, Cocoa ve GNUstep'te Object sınıfı kullanılmaz. - (void) forwardInvocation: (NSInvocation *) anInvocation yöntemi NSObject sınıfına yönlendirme yapmak için kullanılır.

Örnek

İşte yönlendirmenin temellerini gösteren bir program örneği.

iletici.h
#import <objc/Object.h>

@interface Forwarder : Object {
  id recipient; // The object we want to forward the message to.
}

// Accessor methods.
- (id)recipient;
- (id)setRecipient:(id)_recipient;
@end
iletici.m
#import "Forwarder.h"

@implementation Forwarder
- (retval_t)forward:(SEL)sel args:(arglist_t)args {
  /*
  * Check whether the recipient actually responds to the message.
  * This may or may not be desirable, for example, if a recipient
  * in turn does not respond to the message, it might do forwarding
  * itself.
  */
  if ([recipient respondsToSelector:sel]) {
    return [recipient performv:sel args:args];
  } else {
    return [self error:"Recipient does not respond"];
  }
}

- (id)setRecipient:(id)_recipient {
  [recipient autorelease];
  recipient = [_recipient retain];
  return self;
}

- (id)recipient {
  return recipient;
}
@end
alıcı.h
#import <objc/Object.h>

// A simple Recipient object.
@interface Recipient : Object
- (id)hello;
@end
alıcı.m
#import "Recipient.h"

@implementation Recipient

- (id)hello {
  printf("Recipient says hello!\n");

  return self;
}

@end
ana.m
#import "Forwarder.h"
#import "Recipient.h"

int main(void) {
  Forwarder *forwarder = [Forwarder new];
  Recipient *recipient = [Recipient new];

  [forwarder setRecipient:recipient]; // Set the recipient.
  /*
  * Observe forwarder does not respond to a hello message! It will
  * be forwarded. All unrecognized methods will be forwarded to
  * the recipient
  * (if the recipient responds to them, as written in the Forwarder)
  */
  [forwarder hello];

  [recipient release];
  [forwarder release];

  return 0;
}

Notlar

gcc kullanılarak derlendiğinde derleyici şunları bildirir:

$ gcc -x objective-c -Wno-import Forwarder.m Recipient.m main.m -lobjc
main.m: In function `main':
main.m:12: warning: `Forwarder' does not respond to `hello'
$

Derleyici, daha önce belirtilen noktayı, İleticinin merhaba mesajlarına yanıt vermediğini bildiriyor . Bu durumda, yönlendirme uygulandığından uyarıyı göz ardı etmek güvenlidir. Programı çalıştırmak şu çıktıyı üretir:

$ ./a.out
Recipient says hello!

Kategoriler

Objective-C'nin tasarımı sırasında, ana endişelerden biri büyük kod tabanlarının sürdürülebilirliğiydi. Yapılandırılmış programlama dünyasından edinilen deneyimler, kodu iyileştirmenin ana yollarından birinin onu daha küçük parçalara ayırmak olduğunu göstermiştir. Objective-C , bu sürece yardımcı olmak için Smalltalk uygulamalarından kategori kavramını ödünç aldı ve genişletti .

Ayrıca, bir kategori içindeki yöntemler çalışma zamanında bir sınıfa eklenir . Böylece kategoriler, programcının mevcut bir sınıfa - açık bir sınıf - o sınıfı yeniden derlemeye gerek kalmadan veya hatta kaynak koduna erişmeye gerek kalmadan yöntemler eklemesine izin verir . Örneğin, bir sistem String uygulamasında bir yazım denetleyicisi içermiyorsa , String kaynak kodu değiştirilmeden eklenebilir.

Program çalıştırıldığında, kategoriler içindeki yöntemler, bir sınıftaki yöntemlerden ayırt edilemez hale gelir. Bir kategori, özel değişkenler dahil, sınıf içindeki tüm örnek değişkenlere tam erişime sahiptir.

Bir kategori, bir sınıftaki mevcut bir yöntemle aynı yöntem imzasına sahip bir yöntem bildirirse , kategorinin yöntemi benimsenir. Böylece kategoriler yalnızca bir sınıfa yöntem eklemekle kalmaz, aynı zamanda mevcut yöntemlerin yerini alır. Bu özellik, yöntemlerini yeniden yazarak diğer sınıflardaki hataları düzeltmek veya bir program içinde bir sınıfın davranışında genel bir değişikliğe neden olmak için kullanılabilir. İki kategoride aynı ada sahip ancak farklı yöntem imzalarına sahip yöntemler varsa, hangi kategorinin yönteminin benimsendiği tanımlanmaz.

Diğer diller bu özelliği çeşitli şekillerde eklemeye çalışmıştır. TOM , Objective-C sistemini bir adım öteye taşıdı ve değişkenlerin eklenmesine de izin verdi. Diğer diller bunun yerine prototip tabanlı çözümler kullandı, en dikkat çekici olanı Self .

C# ve Visual Basic.NET dilleri, uzantı yöntemleri biçiminde yüzeysel olarak benzer işlevleri uygular , ancak bunların sınıfın özel değişkenlerine erişimi yoktur. Ruby ve diğer birkaç dinamik programlama dili, tekniğe " maymun yaması " olarak atıfta bulunur .

Logtalk , Objective-C kategorileri işlevselliğini kapsayan bir kategori kavramı (birinci sınıf varlıklar olarak) uygular (Logtalk kategorileri, örneğin yeni sınıflar veya prototipler tanımlanırken ince taneli bileşim birimleri olarak da kullanılabilir; özellikle, bir Logtalk kategorisi şu şekilde olabilir: neredeyse herhangi bir sayıda sınıf ve prototip tarafından içe aktarılır).

Kategorilerin örnek kullanımı

Bu örnek, önce yalnızca erişimci yöntemlerinin uygulandığı temel bir sınıf tanımlayarak ve temel sınıfı genişleten Arithmetic ve Display olmak üzere iki kategori ekleyerek bir Tamsayı sınıfı oluşturur . Kategoriler, temel sınıfın özel veri üyelerine erişebilirken, bu özel veri üyelerine erişimci yöntemleri aracılığıyla erişmek genellikle iyi bir uygulamadır; bu, kategorilerin temel sınıftan daha bağımsız kalmasına yardımcı olur. Bu tür erişimcileri uygulamak, kategorilerin tipik bir kullanımıdır. Bir diğeri, temel sınıfa yöntemler eklemek için kategorileri kullanmaktır. Bununla birlikte, maymun yaması olarak da bilinen alt sınıf geçersiz kılma için kategorilerin kullanılması iyi bir uygulama olarak kabul edilmez . Gayri resmi protokoller, temel NSObject sınıfında bir kategori olarak uygulanır . Kural olarak, temel sınıfları genişleten kategoriler içeren dosyalar BaseClass+ExtensionClass.h adını alır .

tamsayı.h
#import <objc/Object.h>

@interface Integer : Object {
  int integer;
}

- (int)integer;
- (id)integer:(int)_integer;
@end
tamsayı.m
#import "Integer.h"

@implementation Integer
- (int) integer {
  return integer;
}

- (id) integer: (int) _integer {
  integer = _integer;
  return self;
}
@end
Tamsayı+Aritmetik.h
#import "Integer.h"

@interface Integer (Arithmetic)
- (id) add: (Integer *) addend;
- (id) sub: (Integer *) subtrahend;
@end
Tamsayı+Aritmetik.m
# import "Integer+Arithmetic.h"

@implementation Integer (Arithmetic)
- (id) add: (Integer *) addend {
  return [self integer: [self integer] + [addend integer]];
}

- (id) sub: (Integer *) subtrahend {
  return [self integer: [self integer] - [subtrahend integer]];
}
@end
Tamsayı+Görüntüleme.h
#import "Integer.h"

@interface Integer (Display)
- (id) showstars;
- (id) showint;
@end
Tamsayı+Görüntüleme.m
# import "Integer+Display.h"

@implementation Integer (Display)
- (id) showstars {
  int i, x = [self integer];
  for (i = 0; i < x; i++) {
    printf("*");
  }
  printf("\n");

  return self;
}

- (id) showint {
  printf("%d\n", [self integer]);

  return self;
}
@end
ana.m
#import "Integer.h"
#import "Integer+Arithmetic.h"
#import "Integer+Display.h"

int main(void) {
  Integer *num1 = [Integer new], *num2 = [Integer new];
  int x;

  printf("Enter an integer: ");
  scanf("%d", &x);

  [num1 integer:x];
  [num1 showstars];

  printf("Enter an integer: ");
  scanf("%d", &x);

  [num2 integer:x];
  [num2 showstars];

  [num1 add:num2];
  [num1 showint];

  return 0;
}

Notlar

Derleme, örneğin şu şekilde gerçekleştirilir:

gcc -x objective-c main.m Integer.m Integer+Arithmetic.m Integer+Display.m -lobjc

Derlemede #import "Integer+Arithmetic.h" ve [num1 add:num2] satırlarını ve Integer+Arithmetic.m satırlarını atlayarak deney yapılabilir . Program çalışmaya devam edecektir. Bu, gerekirse eklenen kategorileri karıştırmanın ve eşleştirmenin mümkün olduğu anlamına gelir ; eğer bir kategorinin bir yeteneğe sahip olması gerekmiyorsa, basitçe derlenemez.

Poz vermek

Objective-C, bir sınıfın bir program içindeki başka bir sınıfı tamamen değiştirmesine izin verir. Değiştirilen sınıfın hedef sınıf "olarak" olduğu söylenir.

Sınıf oluşturma, Mac OS X v10.5 ile kullanımdan kaldırıldı ve 64 bit çalışma zamanında kullanılamaz. Benzer işlevsellik, bir yöntemin uygulamasını aynı imzaya sahip başka bir yöntemin uygulamasını değiştiren kategorilerde yöntem kaydırma kullanılarak elde edilebilir.

Hala poz vermeyi destekleyen sürümler için, hedef sınıfa gönderilen tüm mesajlar bunun yerine poz veren sınıf tarafından alınır. Birkaç kısıtlama vardır:

  • Bir sınıf, yalnızca doğrudan veya dolaylı üst sınıflarından biri olarak ortaya çıkabilir.
  • Poz veren sınıf, hedef sınıfta olmayan herhangi bir yeni örnek değişkeni tanımlamamalıdır (ancak yöntemleri tanımlayabilir veya geçersiz kılabilir).
  • Hedef sınıf, poz vermeden önce herhangi bir mesaj almamış olabilir.

Poz verme, kategorilere benzer şekilde, mevcut sınıfların küresel olarak genişletilmesine izin verir. Poz verme, kategorilerde bulunmayan iki özelliğe izin verir:

  • Poz veren bir sınıf, süper aracılığıyla geçersiz kılınan yöntemleri çağırabilir, böylece hedef sınıfın uygulanmasını dahil edebilir.
  • Bir poz verme sınıfı, kategorilerde tanımlanan yöntemleri geçersiz kılabilir.

Örneğin,

@interface CustomNSApplication : NSApplication
@end

@implementation CustomNSApplication
- (void) setMainMenu: (NSMenu*) menu {
  // do something with menu
}
@end

class_poseAs ([CustomNSApplication class], [NSApplication class]);

Bu, setMainMenu'nun NSApplication'a her çağrısını durdurur.

#içe aktarmak

C dilinde, #includeön derleme yönergesi her zaman bir dosyanın içeriğinin o noktada kaynağa eklenmesine neden olur. Objective-C, #importher bir dosyanın derleme birimi başına yalnızca bir kez dahil edilmesi dışında, include guards gereksinimini ortadan kaldıran, eşdeğer yönergeye sahiptir .

Linux gcc derlemesi

// FILE: hello.m
#import <Foundation/Foundation.h>
int main (int argc, const char * argv[])
{
    /* my first program in Objective-C */
    NSLog(@"Hello, World! \n");
    return 0;
}
# Compile Command Line for gcc and MinGW Compiler:
$ gcc \
    $(gnustep-config --objc-flags) \
    -o hello \
    hello.m \
    -L /GNUstep/System/Library/Libraries \
    -lobjc \
    -lgnustep-base

$ ./hello

Diğer özellikler

Objective-C'nin özellikleri genellikle programlama sorunlarına esnek ve genellikle kolay çözümler sağlar.

  • Yöntemleri diğer nesnelere devretme ve uzaktan çağırma , kategoriler ve mesaj iletme kullanılarak kolayca uygulanabilir.
  • isa işaretçisinin döndürülmesi , sınıfların çalışma zamanında değişmesine izin verir. Genellikle , serbest bırakılan nesnelerin, biri onları aradığında bir hatayı bildirmek olan tek amacı zombi nesnelere dönüştürüldüğü hata ayıklama için kullanılır . Swizzling, Enterprise Objects Framework'te veritabanı hataları oluşturmak için de kullanıldı . Swizzling, bugün Apple'ın Foundation Framework tarafından Key-Value Observing'i uygulamak için kullanılmaktadır .

Dil çeşitleri

Amaç-C++

Objective-C++, C++ ve Objective-C sözdiziminin bir kombinasyonunu kullanan kaynak dosyaları derleyebilen GNU Compiler Collection ve Clang'ın ön uç tarafından kabul edilen bir dil çeşididir . Objective-C++, Objective-C'nin C'ye eklediği uzantıları C++'a ekler. Çeşitli dil özelliklerinin arkasındaki semantiği birleştirmek için hiçbir şey yapılmadığından, belirli kısıtlamalar uygulanır:

  • Bir C++ sınıfı, bir Objective-C sınıfından türetilemez ve bunun tersi de geçerlidir.
  • C++ ad alanları, bir Objective-C bildirimi içinde bildirilemez.
  • Objective-C bildirimleri, bir C++ ad alanı içinde değil, yalnızca genel kapsamda görünebilir
  • Objective-C sınıfları, varsayılan bir oluşturucusu olmayan veya bir veya daha fazla sanal yöntemi olan C++ sınıflarının örnek değişkenlerine sahip olamaz , ancak C++ nesnelerine yönelik işaretçiler, kısıtlama olmaksızın örnek değişkenler olarak kullanılabilir (bunları -init yönteminde new ile ayırın).
  • C++ "değerine göre" semantiği, yalnızca işaretçiler aracılığıyla erişilebilen Objective-C nesnelerine uygulanamaz.
  • Bir Objective-C bildirimi, bir C++ şablon bildirimi içinde olamaz ve bunun tersi de geçerlidir. Ancak Objective-C türleri (örn. Classname *), C++ şablon parametreleri olarak kullanılabilir.
  • Objective-C ve C++ özel durum işleme farklıdır; her birinin işleyicileri diğer türün istisnalarını işleyemez. Sonuç olarak, nesne yıkıcılar çalıştırılmaz. Objective-C istisnaları ya tamamen C++ istisnaları ile değiştirildiğinden (Apple çalışma zamanı) veya kısmen Objective-C++ kitaplığı bağlandığında (GNUstep libobjc2) bu son "Objective-C 2.0" çalışma zamanlarında azaltılmıştır.
  • Objective-C blokları ve C++11 lambdaları farklı varlıklardır. Ancak, bir bloğun beklendiği yerde bir lambda geçirilirken macOS'ta şeffaf bir şekilde bir blok oluşturulur.

Amaç-C 2.0

2006 Dünya Çapında Geliştiriciler Konferansı'nda Apple, Objective-C dilinin "modern çöp toplama, sözdizimi geliştirmeleri, çalışma zamanı performans iyileştirmeleri ve 64 bit desteği" içerecek şekilde bir revizyonu olan "Objective-C 2.0"ın yayınlandığını duyurdu. Ekim 2007'de piyasaya sürülen Mac OS X v10.5 , bir Objective-C 2.0 derleyicisi içeriyordu. GCC 4.6 , bildirilen ve sentezlenen özellikler, nokta sözdizimi, hızlı numaralandırma, isteğe bağlı protokol yöntemleri, yöntem/protokol/sınıf öznitelikleri, sınıf uzantıları ve yeni bir GNU Objective-C çalışma zamanı API'si gibi birçok yeni Objective-C özelliğini destekler.

NeXT için son Objective-C sürümü "objc4" olduğundan, Objective-C 2.0 adlandırması, dilin sürüm oluşturma sisteminde bir kırılmayı temsil eder. Bu proje adı, Mac OS X Leopard'da (10.5) eski Objective-C çalışma zamanı kaynak kodunun son sürümünde tutuldu .

Çöp toplama

Objective-C 2.0, isteğe bağlı bir muhafazakar, nesil çöp toplayıcı sağladı . Geriye dönük uyumlu modda çalıştırıldığında , çalışma zamanı "saklama" ve "bırakma" gibi referans sayma işlemlerini işlemsiz hale getirdi . Çöp toplama etkinleştirildiğinde tüm nesneler çöp toplamaya tabiydi. Normal C işaretçileri, altta yatan yazma engeli derleyici engellemelerini tetiklemek ve böylece çöp toplamaya katılmak için "__strong" ile nitelenebilir. Nesne (veya daha basit olarak, GC belleği) toplandığında "__weak" olarak işaretlenen işaretçilerin sıfıra ayarlanması için sıfırlanan zayıf bir alt sistem de sağlandı. Çöp toplayıcı, Objective-C 2.0'ın iOS uygulamasında mevcut değil. Objective-C'deki çöp toplama, düşük öncelikli bir arka plan iş parçacığı üzerinde çalışır ve kullanıcı deneyimini duyarlı tutmak amacıyla kullanıcı etkinliklerinde durabilir.

Çöp toplama, Mac OS X v10.8'de Otomatik Referans Sayma (ARC) lehine kullanımdan kaldırıldı . ARM64 üzerinde çalışan iOS 7'deki Objective-C, bir etiketli işaretçi biçimi olarak referans sayısını depolamak için 64 bitlik bir kelimenin 19 bitini kullanır .

Özellikler

Objective-C 2.0 , erişimci yöntemlerinin oluşturulmasını yapılandırmak için isteğe bağlı özniteliklerle, örnek değişkenleri özellikler olarak bildirmek için yeni bir sözdizimi sunar . Özellikler, bir anlamda, genel örnek değişkenleridir; yani, bir örnek değişkeni bir özellik olarak bildirmek, harici sınıflara o özelliğe erişim (muhtemelen sınırlı, örneğin salt okunur) sağlar. Bir özellik "salt okunur" olarak bildirilebilir ve assign, copyveya gibi depolama semantiği ile sağlanabilir retain. Varsayılan olarak, özellikler dikkate alınır atomicve bu, birden çok iş parçacığının aynı anda bunlara erişmesini engelleyen bir kilitle sonuçlanır. nonatomicBu kilidi kaldıran bir özellik olarak bildirilebilir .

@interface Person : NSObject {
@public
  NSString *name;
@private
  int age;
}

@property(copy) NSString *name;
@property(readonly) int age;

- (id)initWithAge:(int)age;
@end

Özellikler @synthesize, özellik bildirimine göre alıcı (ve salt okunur değilse ayarlayıcı) yöntemleri üreten anahtar sözcük aracılığıyla uygulanır . Alternatif olarak, alıcı ve ayarlayıcı yöntemleri açıkça uygulanmalıdır veya @dynamicanahtar sözcük, erişimci yöntemlerin başka yollarla sağlanacağını belirtmek için kullanılabilir. Clang 3.1 veya üstü kullanılarak derlendiğinde, ile açıkça bildirilmeyen @dynamic, işaretlenmeyen readonlyveya tam kullanıcı tarafından uygulanan alıcı ve ayarlayıcıya sahip olan tüm özellikler otomatik olarak örtük olarak @synthesize'd' olacaktır .

@implementation Person
@synthesize name;

- (id)initWithAge:(int)initAge {
  self = [super init];
  if (self) {
    // NOTE: direct instance variable assignment, not property setter
    age = initAge;
  }
  return self;
}

- (int)age {
  return age;
}
@end

Özellikler, geleneksel mesaj geçiş sözdizimi, nokta gösterimi veya Anahtar-Değer Kodlamada, "valueForKey:"/"setValue:forKey:" yöntemleri aracılığıyla ada göre erişilebilir.

Person *aPerson = [[Person alloc] initWithAge:53];
aPerson.name = @"Steve"; // NOTE: dot notation, uses synthesized setter,
                         // equivalent to [aPerson setName: @"Steve"];
NSLog(@"Access by message (%@), dot notation(%@), property name(% @) and "
       "direct instance variable access(% @) ",
              [aPerson name],
      aPerson.name, [aPerson valueForKey:@"name"], aPerson -> name);

Bir örnek yönteminde özellik erişimcilerini çağırmak için nokta gösterimini kullanmak için "self" anahtar sözcüğü kullanılmalıdır:

- (void)introduceMyselfWithProperties:(BOOL)useGetter {
  NSLog(@"Hi, my name is %@.", (useGetter ? self.name : name));
  // NOTE: getter vs. ivar access
}

Bir sınıfın veya protokolün özellikleri dinamik olarak iç gözlemlenebilir .

int i;
int propertyCount = 0;
objc_property_t *propertyList =
    class_copyPropertyList([aPerson class], &propertyCount);

for (i = 0; i < propertyCount; i++) {
  objc_property_t *thisProperty = propertyList + i;
  const char *propertyName = property_getName(*thisProperty);
  NSLog(@"Person has a property: '%s'", propertyName);
}

Kırılgan olmayan örnek değişkenleri

Objective-C 2.0, çalışma zamanı tarafından desteklendiğinde (yani 64-bit macOS ve tüm iOS için kod oluştururken) kırılgan olmayan örnek değişkenleri sağlar. Modern çalışma zamanı altında, örnek değişken erişimine fazladan bir dolaylı katman eklenir ve bu, dinamik bağlayıcının çalışma zamanında örnek düzenini ayarlamasına olanak tanır. Bu özellik, Objective-C kodunda iki önemli iyileştirmeye olanak tanır:

  • Kırılgan ikili arabirim sorununu ortadan kaldırır ; üst sınıflar, ikili uyumluluğu etkilemeden boyutları değiştirebilir.
  • Özellikler için destek sağlayan örnek değişkenlerin, sınıfın arabiriminde bildirilmeden çalışma zamanında sentezlenmesine izin verir.

Hızlı numaralandırma

Bir koleksiyonda yineleme yapmak için bir NSEnumerator nesnesi veya dizinleri kullanmak yerine, Objective-C 2.0 hızlı numaralandırma sözdizimini sunar. Objective-C 2.0'da aşağıdaki döngüler işlevsel olarak eşdeğerdir, ancak farklı performans özelliklerine sahiptir.

// Using NSEnumerator
NSEnumerator *enumerator = [thePeople objectEnumerator];
Person *p;

while ((p = [enumerator nextObject]) != nil) {
  NSLog(@"%@ is %i years old.", [p name], [p age]);
}
// Using indexes
for (int i = 0; i < [thePeople count]; i++) {
  Person *p = [thePeople objectAtIndex:i];
  NSLog(@"%@ is %i years old.", [p name], [p age]);
}
// Using fast enumeration
for (Person *p in thePeople) {
  NSLog(@"%@ is %i years old.", [p name], [p age]);
}

Hızlı numaralandırma, standart numaralandırmadan daha verimli kod üretir, çünkü nesneler üzerinde numaralandırmaya yönelik yöntem çağrıları, NSFastEnumeration protokolü kullanılarak işaretçi aritmetiği ile değiştirilir.

Sınıf uzantıları

Bir sınıf uzantısı, kategori adı olmayan bir kategori bildirimi ile aynı sözdizimine sahiptir ve içinde bildirilen yöntemler ve özellikler doğrudan ana sınıfa eklenir. Sınıf uzantıları için derleyicinin özel olarak bildirilen tüm yöntemlerin gerçekten uygulanıp uygulanmadığını kontrol etmesi avantajıyla, bir sınıfa yöntemleri genel başlıklarda tanıtmadan eklemek için çoğunlukla bir kategoriye alternatif olarak kullanılır.

Kakao gelişimi için çıkarımlar

macOS için geliştirilen ve Objective-C 2.0 için yukarıdaki iyileştirmelerden yararlanan tüm Objective-C uygulamaları, 10.5'ten (Leopard) önceki tüm işletim sistemleriyle uyumlu değildir. Hızlı numaralandırma, standart numaralandırma ile tam olarak aynı ikili dosyaları oluşturmadığından, kullanımı bir uygulamanın Mac OS X sürüm 10.4 veya önceki sürümlerde çökmesine neden olur.

Bloklar

Blocks, closures oluşturmak için özel sözdizimi kullanan Objective-C (ve C ve C++ ) için standart olmayan bir uzantıdır . Bloklar yalnızca Mac OS X 10.6 "Snow Leopard" veya üstü, iOS 4 veya üstü ve libobjc2 1.7 ile GNUstep ve clang 3.1 veya üstü ile derlemede desteklenir .

#include <stdio.h>
#include <Block.h>
typedef int (^IntBlock)();

IntBlock MakeCounter(int start, int increment) {
  __block int i = start;

  return Block_copy( ^ {
    int ret = i;
    i += increment;
    return ret;
  });

}

int main(void) {
  IntBlock mycounter = MakeCounter(5, 2);
  printf("First call: %d\n", mycounter());
  printf("Second call: %d\n", mycounter());
  printf("Third call: %d\n", mycounter());

  /* because it was copied, it must also be released */
  Block_release(mycounter);

  return 0;
}
/* Output:
  First call: 5
  Second call: 7
  Third call: 9
*/

Modern Amaç-C

Apple, zamanla Objective 2.0'a bazı ek özellikler ekledi. Eklemeler yalnızca "Apple LLVM derleyicisi" için geçerlidir , yani dilin clang ön ucu. Şaşırtıcı bir şekilde, Apple tarafından kullanılan sürüm oluşturma, LLVM yukarı akışınınkinden farklıdır; açık kaynaklı LLVM sürüm numaralarına çeviri için Xcode § Toolchain sürümlerine bakın .

Otomatik Referans Sayımı

Otomatik Referans Sayımı (ARC), programcıların alıkoyma sayılarını retainve kullanarak manuel olarak yönetme ihtiyacını ortadan kaldıran bir derleme zamanı özelliğidir release. Çalışma zamanında gerçekleşen çöp toplamanın aksine , ARC, tutma sayılarını yöneten ayrı bir işlemin ek yükünü ortadan kaldırır. ARC ve manuel bellek yönetimi birbirini dışlamaz; programcılar, bireysel kod dosyaları için ARC'yi devre dışı bırakarak ARC-etkin projelerde ARC olmayan kodu kullanmaya devam edebilirler. Xcode, bir projeyi otomatik olarak ARC'ye yükseltmeyi de deneyebilir.

ARC, LLVM 3.0'da tanıtıldı. Bu, Xcode 4.2 (2011) veya Apple LLVM derleyici 3.0 anlamına gelir.

değişmezler

NeXT ve Apple Obj-C çalışma zamanları, uzun süredir, değişmez sözdizimini kullanarak @"a new string"veya CoreFoundation sabitlerine kCFBooleanTrueve kCFBooleanFalsefor NSNumberBoole değerleriyle yeni dizeler oluşturmak için kısa biçimli bir yol içeriyor . Bu formatı kullanmak, programcıyı initWithStringbelirli işlemleri yaparken daha uzun veya benzer yöntemleri kullanmaktan kurtarır .

Apple LLVM derleyici 4.0 (Xcode 4.4) veya sonraki bir sürümünü kullanırken diziler, sözlükler ve sayılar ( NSArray, NSDictionary, NSNumbersınıflar) yöntemler yerine değişmez sözdizimi kullanılarak da oluşturulabilir. (Apple LLVM derleyici 4.0, açık kaynaklı LLVM ve Clang 3.1'e çevirir.)

Değişmezsiz örnek:

NSArray *myArray = [NSArray arrayWithObjects:object1,object2,object3,nil];
NSDictionary *myDictionary1 = [NSDictionary dictionaryWithObject:someObject forKey:@"key"];
NSDictionary *myDictionary2 = [NSDictionary dictionaryWithObjectsAndKeys:object1, key1, object2, key2, nil];
NSNumber *myNumber = [NSNumber numberWithInt:myInt];
NSNumber *mySumNumber= [NSNumber numberWithInt:(2 + 3)];
NSNumber *myBoolNumber = [NSNumber numberWithBool:YES];

Harflerle örnek:

NSArray *myArray = @[ object1, object2, object3 ];
NSDictionary *myDictionary1 = @{ @"key" : someObject };
NSDictionary *myDictionary2 = @{ key1: object1, key2: object2 };
NSNumber *myNumber = @(myInt);
NSNumber *mySumNumber = @(2+3);
NSNumber *myBoolNumber = @YES;
NSNumber *myIntegerNumber = @8;

Ancak, yürütülebilir dosyadaki sabitleri derleyen dize değişmezlerinden farklı olarak , bu değişmez değerler, yukarıdaki yöntem çağrılarına eşdeğer bir kod için derlenir. Özellikle, manüel olarak başvuru sayılan bellek yönetimi altında, bu nesneler, örneğin, fonksiyon-statik değişkenler veya başka türde globallerle kullanıldığında daha fazla özen gerektiren, otomatik olarak serbest bırakılır.

Abonelik

Apple LLVM derleyici 4.0 veya sonraki bir sürümünü kullanırken , diziler ve sözlükler ( NSArrayve NSDictionarysınıflar) abonelik kullanılarak değiştirilebilir. Abonelik, dizinlerden (dizi) veya anahtarlardan (sözlük) değerleri almak için kullanılabilir ve değiştirilebilir nesnelerle, nesneleri dizinlere veya anahtarlara ayarlamak için de kullanılabilir. Kodda, abonelik parantezler kullanılarak temsil edilir [ ].

Abone olmadan örnek:

id object1 = [someArray objectAtIndex:0];
id object2 = [someDictionary objectForKey:@"key"];
[someMutableArray replaceObjectAtIndex:0 withObject:object3];
[someMutableDictionary setObject:object4 forKey:@"key"];

Abonelik ile örnek:

id object1 = someArray[0];
id object2 = someDictionary[@"key"];
someMutableArray[0] = object3;
someMutableDictionary[@"key"] = object4;

"Modern" Objective-C sözdizimi (1997)

NeXT'nin Apple tarafından satın alınmasından sonra, dili Java'ya Smalltalk'tan daha aşina olan programcılar için daha kabul edilebilir kılmak için girişimlerde bulunuldu . Bu girişimlerden biri, o sırada Objective-C için "Modern Sözdizimi" olarak adlandırılan şeyi tanıtmaktı (mevcut "klasik" sözdiziminin aksine). Davranışta herhangi bir değişiklik olmadı, bu sadece alternatif bir sözdizimiydi. Gibi bir yöntem çağrısı yazmak yerine

    object = [[MyClass alloc] init];
    [object firstLabel: param1 secondLabel: param2];

Bunun yerine şöyle yazılmıştır:

    object = (MyClass.alloc).init;
    object.labels ( param1, param2 );

Benzer şekilde, beyanlar formdan gitti

    -(void) firstLabel: (int)param1 secondLabel: (int)param2;

ile

    -(void) labels ( int param1, int param2 );

Bu "modern" sözdizimi, Objective-C dilinin mevcut lehçelerinde artık desteklenmemektedir.

mulle-objc

Mulle-objc proje Objective-C diğer bir yeniden uygulamasıdır. Arka uç olarak GCC veya Clang / LLVM derleyicilerini destekler . Sözdizimi, anlambilim ve ABI uyumluluğu açısından diğer çalışma zamanlarından ayrılır. Linux, FreeBSD ve Windows'u destekler.

Taşınabilir Nesne Derleyici

Orijinal Stepstone uygulamasına birkaç uzantı ekleyen GCC / NeXT / Apple uygulamasının yanı sıra, Portable Object Compiler adlı başka bir ücretsiz, açık kaynaklı Objective-C uygulaması da mevcuttur. Portable Object Compiler tarafından uygulanan uzantı seti, GCC/NeXT/Apple uygulamasından farklıdır; özellikle, Objective-C için Smalltalk benzeri blokları içerir , protokoller ve kategorilerden yoksundur, OpenStep ve türevleri ve akrabalarında yaygın olarak kullanılan iki özellik. Genel olarak, POC, dilin evriminde, Brad Cox'un 1991 tarihli kitabına kabaca uygun olan, daha eski, NeXT öncesi bir aşamayı temsil eder.

Ayrıca, Cox'un orijinal ICPak101 kitaplığına (sırasıyla Smalltalk-80 sınıf kitaplığından türetilmiştir) dayanan ve OpenStep FoundationKit'ten oldukça farklı olan ObjectPak adlı bir çalışma zamanı kitaplığı içerir.

GEOS Amaç-C

PC GEOS sistemi olarak bilinen bir programlama dili kullanılan GEOS Objective-C veya GOC ; İsim benzerliğine rağmen, iki dil sadece genel konsept ve @ işareti ile ön eklenmiş anahtar kelimelerin kullanımı bakımından benzerdir.

klan

Clang derleyici paketi, bir kısmı LLVM projesi uygular Objective-C ve diğer diller. GCC 4.3 (2008) GPLv3'e geçtikten sonra Apple, daha fazla yasal güce sahip olan bir derleyici olan clang lehine onu terk etti. Sonuç olarak, modern Objective-C dil özelliklerinin çoğu yalnızca Clang tarafından desteklenir.

Apple'ın klan tabanlı "LLVM derleyicisi" için sürüm oluşturma şeması, LLVM'nin açık kaynaklı sürüm oluşturmasından farklıdır. Bir çeviri için Xcode § Toolchain sürümlerine bakın

GNU, GNUstep ve WinObjC

GNU projesi, uzun süredir NeXT ve Obj-C programlarını taşımak için bir platformla ilgileniyor. GCC'deki libobjc dizini için ChangeLog, 1998'den önce var olduğunu (GCC 2.95) ve README'nin 1993'te yeniden yazıldığını (GCC 2.4) işaret ediyor.

NeXT ön uç kaynak kodu, GCC'nin bir parçası olarak yapıldığı için yayınlandı, türev çalışmalar yapanları bunu yapmaya zorlayan GNU Kamu Lisansı'nı yayınladı . Apple, GCC çatalını 4.2.1'e kadar serbest bırakarak bu geleneği sürdürdü ve ardından derleyiciyi terk etti. GCC bakımcıları değişiklikleri üstlendi, ancak Objective-C 2.0 dili gibi daha yeni özellikleri desteklemek için fazla yatırım yapmadı.

Yeni dille ilgilenen GNUstep geliştiricileri, GCC libobjc'yi 2009 yılında libobjc2 adlı GCC'den bağımsız bir projeye çatalladılar . Ayrıca, yeni dil sözdiziminden yararlanmak için çalışma zamanının Clang ile birlikte kullanılmasını da ayarladılar. GCC aynı zamanda yavaş hareket etti, ancak GCC 4.6.0'da (2011) libobjc'lerinde Objective-C 2.0'a geçtiler. GNUstep belgeleri, GCC uygulamasının hala bloklar, kırılgan olmayan değişkenler ve daha yeni ARC desteğinden yoksun olduğunu göstermektedir.

Microsoft, çatallı libobjc2 bir parçası haline WinObjC için iOS köprü Evrensel Windows Platformunda kendi uygulamasıyla 2015 Kombine içinde, Kakao dokunun ve alttaki API'ler, proje UWP uygulamalar iOS Uygulama kodu içeriden yeniden kullanılmasına olanak tanır.

Windows'ta, Objective-C Geliştirme araçları GNUStep'in web sitesinde indirilmek üzere sağlanmıştır. GNUStep Geliştirme Sistemi aşağıdaki paketlerden oluşur: GNUstep MSYS System, GNUstep Core, GNUstep Devel, GNUstep Cairo, ProjectCenter IDE (Xcode gibi ama karmaşık değil), Gorm (Interface Builder Like Xcode NIB oluşturucu). Bu ikili yükleyiciler 2016'dan beri güncellenmedi, bu nedenle bunun yerine Cygwin veya MSYS2 altında inşa ederek kurmak daha iyi bir fikir olabilir .

Kütüphane kullanımı

Bugün Objective-C genellikle Cocoa , GNUstep veya ObjFW gibi sabit bir standart nesne kitaplığı (genellikle "kit" veya "çerçeve" olarak bilinir) ile birlikte kullanılır . Bu kitaplıklar genellikle işletim sistemiyle birlikte gelir: GNUstep kitaplıkları genellikle Linux tabanlı dağıtımlarla birlikte gelir ve Cocoa, macOS ile birlikte gelir. Programcı, mevcut temel sınıftan (NSObject / OFObject) işlevselliği devralmaya zorlanmaz. Objective-C, mevcut herhangi bir işlevi devralmayan yeni kök sınıfların bildirilmesine izin verir. Başlangıçta, Objective-C tabanlı programlama ortamları, neredeyse tüm diğer sınıfların miras aldığı temel sınıf olarak tipik olarak bir Object sınıfı sunuyordu. OpenStep'in piyasaya sürülmesiyle NeXT, NSObject adında yeni bir temel sınıf yarattı ve bu sınıf, Object üzerinden ek özellikler (örneğin, ham işaretçiler yerine nesne referansları ve referans sayımının kullanılmasına vurgu yaptı). Cocoa'daki hemen hemen tüm sınıflar NSObject'den miras alır.

Yeniden adlandırma yalnızca OpenStep API'sindeki sınıfların yeni varsayılan davranışını ayırt etmeye hizmet etmekle kalmadı, aynı zamanda NeXTSTEP'te (ve aşağı yukarı diğer Objective-C sınıf kitaplıklarında) kullanılan orijinal temel sınıf olan Object'i kullanan kodun NSObject'i kullanan kodla (bazı sınırlamalarla) aynı çalışma zamanında birlikte bulunur. İki harfli önek, aynı zamanda Objective-C'nin yoksun olduğu basit bir ad alanı biçimi haline geldi. Resmi olmayan bir paketleme tanımlayıcısı oluşturmak için bir önek kullanmak, Objective-C topluluğunda resmi olmayan bir kodlama standardı haline geldi ve bu güne kadar devam ediyor.

Daha yakın zamanlarda, hem paket yöneticisi hem de paket deposu olmayı amaçlayan CocoaPods gibi paket yöneticileri ortaya çıkmaya başladı . Son birkaç yılda yazılan birçok açık kaynaklı Objective-C kodu artık CocoaPod'lar kullanılarak kurulabilir.

Dilin analizi

Objective-C uygulamaları , C ile yazılmış ve uygulamanın boyutuna çok az katkıda bulunan ince bir çalışma zamanı sistemi kullanır . Buna karşılık, çoğu nesne yönelimli sistem, oluşturuldukları sırada büyük sanal makine çalışma zamanları kullanıyordu. Objective-C'de yazılan programlar, büyük miktarda belleğin olduğu Smalltalk sistemlerinin aksine, kodlarının ve kitaplıkların (genellikle yazılım dağıtımına dahil edilmesi gerekmeyen) boyutundan çok daha büyük olmama eğilimindedir. sadece bir pencere açmak için kullanılır. Objective-C uygulamaları, benzer C veya C++ uygulamalarından daha büyük olma eğilimindedir, çünkü Objective-C dinamik yazma, yöntemlerin çıkarılmasına veya satır içine alınmasına izin vermez. Programcı, çağrıları devretme, yönlendirme, anında seçiciler oluşturma ve bunları çalışma zamanı sistemine geçirme özgürlüğüne sahip olduğundan, Objective-C derleyicisi, kullanılmayan yöntemleri kaldırmanın veya satır içi çağrıların güvenli olduğunu varsayamaz.

Benzer şekilde, dil, yeni bir derleyici yerine mevcut C derleyicilerinin ( GCC'de önce önişlemci, sonra modül olarak) üzerine uygulanabilir. Bu, Objective-C'nin mevcut devasa C kodu, kitaplıklar, araçlar vb. koleksiyonundan yararlanmasını sağlar. Mevcut C kitaplıkları, OO tarzı bir arayüz sağlamak için Objective-C sarmalayıcılarına sarılabilir . Bu yönüyle GTK uygulamalarının geliştirilmesinde yaygın olarak kullanılan GObject kütüphanesi ve Vala dili ile benzerlik göstermektedir .

Tüm bu pratik değişiklikler , 1980'lerde Smalltalk'ın yaygın kabulü için muhtemelen en büyük sorun olan giriş engelini düşürdü .

Yaygın bir eleştiri, Objective-C'nin ad alanları için dil desteğine sahip olmamasıdır . Bunun yerine, programcılar, sınıf adlarına, geleneksel olarak ad alanı adlarından daha kısa olan ve dolayısıyla çarpışmalara daha yatkın olan önekler eklemek zorunda kalırlar. 2007 itibariyle, Cocoa programlama ortamındaki tüm macOS sınıfları ve işlevleri, onları macOS veya iOS çekirdeğine ait olarak tanımlamak için "NS" (örn. NSObject, NSButton) ile öneklenmiştir; "NS", NeXTSTEP'in geliştirilmesi sırasında tanımlanan sınıfların adlarından türemiştir .

Objective-C, C'nin katı bir üst kümesi olduğundan, C ilkel türlerini birinci sınıf nesneler olarak ele almaz .

C++ 'dan farklı olarak Objective-C, operatör aşırı yüklemesini desteklemez . Ayrıca, C++ 'dan farklı olarak Objective-C, bir nesnenin yalnızca bir sınıftan doğrudan miras almasına izin verir ( birden çok kalıtımı yasaklar ). Bununla birlikte, çoğu durumda, kategoriler ve protokoller, aynı sonuçları elde etmenin alternatif yolları olarak kullanılabilir.

Objective-C dinamik çalışma zamanı yazmayı kullandığından ve tüm yöntem çağrıları işlev çağrıları (veya bazı durumlarda sistem çağrıları) olduğundan, birçok yaygın performans optimizasyonu Objective-C yöntemlerine uygulanamaz (örneğin: satır içi, sabit yayılım, prosedürler arası optimizasyonlar, ve agregaların skaler yer değiştirmesi). Bu, bu tür optimizasyonların mümkün olduğu C++ gibi dillerdeki benzer soyutlamalara göre Objective-C soyutlamalarının performansını sınırlar.

Hafıza yönetimi

Objective-C'nin ilk sürümleri çöp toplamayı desteklemiyordu . O zamanlar bu karar bir tartışma konusuydu ve birçok kişi tüm sistemi kullanılamaz hale getirmek için uzun "ölü zamanları" (Smalltalk toplama gerçekleştirdiği zaman) düşündü. Bazı 3. parti uygulamalar bu özelliği eklemiştir (özellikle GNUstep Boehm kullanarak ) ve Apple bunu Mac OS X v10.5'ten itibaren uygulamaya koymuştur . Ancak, macOS ve iOS'un daha yeni sürümlerinde çöp toplama, 2011'de tanıtılan Otomatik Referans Sayma (ARC) lehine kullanımdan kaldırılmıştır .

ARC ile derleyici, statik kod analizine dayalı olarak, çağrıları otomatik olarak Objective-C koduna ekler ve serbest bırakır . Otomasyon, programcıyı bellek yönetimi kodu yazmak zorunda olmaktan kurtarır. ARC ayrıca Objective-C diline zayıf referanslar ekler.

Objective-C ve C++ arasındaki felsefi farklılıklar

C++ ve Objective-C'nin tasarımı ve uygulanması, C'yi genişletmeye yönelik temelde farklı yaklaşımları temsil eder.

C'nin prosedürel programlama stiline ek olarak, C++ doğrudan belirli nesne yönelimli programlama , genel programlama ve metaprogramlama biçimlerini destekler . C++ ayrıca birkaç kapsayıcı sınıfı içeren geniş bir standart kitaplıkla birlikte gelir . Benzer şekilde, Objective-C, C'ye nesne yönelimli programlama , dinamik yazma ve yansıma ekler . Objective-C, kendi başına standart bir kitaplık sağlamaz , ancak Objective-C'nin kullanıldığı çoğu yerde, OpenStep benzeri bir kitaplık ile kullanılır. gibi kütüphane OpenStep'in , kakao veya GNUstep'e C ++ 'ın standart kitaplığı benzer bir işlevsellik sağlar.

Dikkate değer bir fark, Objective-C'nin yansıtıcı özellikler için çalışma zamanı desteği sağlamasına karşın, C++'ın C'ye yalnızca küçük bir miktarda çalışma zamanı desteği eklemesidir. Objective-C'de, bir nesnenin kendi özellikleri hakkında sorgulanabilir, örn. belirli bir mesaj. C++'da bu, harici kütüphaneler kullanılmadan mümkün değildir.

Yansıma kullanımı, bir dilin dinamik (çalışma zamanı) özellikleri ile statik (derleme zamanı) özellikleri arasındaki daha geniş ayrımın bir parçasıdır. Objective-C ve C++ her iki özelliğin bir karışımını kullanmasına rağmen, Objective-C kesinlikle çalışma zamanı kararlarına yöneliktir, C++ ise derleme zamanı kararlarına yöneliktir. Dinamik ve statik programlama arasındaki gerilim, programlamadaki klasik ödünleşimlerin çoğunu içerir: dinamik özellikler esneklik katar, statik özellikler hız ve tip denetimi ekler.

Genel programlama ve metaprogramlama, çalışma zamanı polimorfizmi kullanılarak her iki dilde de uygulanabilir . C++'da bu, sanal işlevler ve çalışma zamanı türü tanımlama biçimini alırken, Objective-C dinamik yazma ve yansıtma sunar. Hem Objective-C hem de C++, derleme zamanı polimorfizmini ( genel işlevler ) destekler, Objective-C bu özelliği yalnızca 2015'te ekler.

Ayrıca bakınız

Referanslar

daha fazla okuma

  • Cox, Brad J. (1991). Nesne Yönelimli Programlama: Evrimsel Bir Yaklaşım . Addison Wesley. ISBN'si 0-201-54834-8.

Dış bağlantılar