Neden bir Objective-C yöntem adının son bölümü bir bağımsız değişken almalıdır (birden fazla bölüm varken)?


90

Objective-C'de, son bileşenin bir argüman almadığı durumlarda yöntem adlarını bildiremezsiniz. Örneğin, aşağıdaki yasa dışıdır.

-(void)take:(id)theMoney andRun;
-(void)take:(id)yourMedicine andDontComplain;

Objective-C neden bu şekilde tasarlandı? Kimsenin kurtulmaya ihtiyaç duymadığı, Smalltalk'ın bir eseri miydi?

Bu sınırlama Smalltalk'da anlamlıdır, çünkü Smalltalk mesaj çağırma etrafında sınırlayıcılara sahip değildir, bu nedenle son bileşen, son argümana tek bir mesaj olarak yorumlanacaktır. Örneğin, BillyAndBobby take:'$100' andRunolarak ayrıştırılır BillyAndBobby take:('$100' andRun). Köşeli parantezlerin gerekli olduğu Objective-C'de bu önemli değildir.

Parametresiz seçici bileşenlerin desteklenmesi, bir programcının seçtiği yöntem adı olarak (örneğin runWith:,take:andRun) bir programın işlevsel anlamını veya dilin ifade gücünü etkilemez. Gerçekte, parametresiz bileşenlere sahip bir program, içermeyen bir programın alfa eşdeğeridir. Bu nedenle, böyle bir özelliğin gerekli olmadığını belirten yanıtlarla ilgilenmiyorum (Objective-C tasarımcılarının belirtilen nedenleri bu değilse; Brad Cox veya Tom Love'ı tanıyan var mı? Burada mı?) özelliğe gerek kalmaması için yöntem adlarının nasıl yazılacağı. Birincil fayda, okunabilirlik ve yazılabilirliktir (ki bu okunabilirlik gibidir, sadece ... bilirsiniz), çünkü bu, doğal dil cümlelerine daha çok benzeyen yöntem isimleri yazabileceğiniz anlamına gelir. Sevmez -(BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication*)theApplicationki Matt Gallagher işaret ( "Kakao With Love" üzerine-(BOOL)application:(NSApplication*)theApplication shouldTerminateAfterLastWindowClosed, böylece parametre hemen uygun ismin yanına yerleştirilir.

Apple'ın Objective-C çalışma zamanı (örneğin) bu tür seçicileri mükemmel şekilde idare edebilir, öyleyse neden derleyici olmasın? Neden onları yöntem adlarında da desteklemiyorsunuz?

#import <Foundation/Foundation.h>
#import <objc/runtime.h>

@interface Potrzebie : NSObject
-(void)take:(id)thing;
@end

@implementation Potrzebie
+(void)initialize {
    SEL take_andRun = NSSelectorFromString(@"take:andRun");
    IMP take_ = class_getMethodImplementation(self, @selector(take:));
    if (take_) {
        if (NO == class_addMethod(self, take_andRun, take_, "@@:@")) {
            NSLog(@"Couldn't add selector '%@' to class %s.", 
                  NSStringFromSelector(take_andRun), 
                  class_getName(self));
        }
    } else {
        NSLog(@"Couldn't find method 'take:'.");
    }
}

-(void)take:(id)thing {
    NSLog(@"-take: (actually %@) %@",NSStringFromSelector(_cmd), thing);
}
@end

int main() {
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

    Potrzebie *axolotl=[[Potrzebie alloc] init];
    [axolotl take:@"paradichloroaminobenzaldehyde"];
    [axolotl performSelector:NSSelectorFromString(@"take:andRun") 
                  withObject:@"$100"];
    [axolotl release];

    [pool release];
    return 0;
}

1
Bunun neden mümkün olmadığını açıklayamıyorum, ama bu neden mümkün olsun? Apple, "takeAndRun:" ve "takeAndDontComplain:";)

Veya takeAndRunWith:(id)theMoneyve takeAndDon'tComplainAbout:(id)yourMedicine. Emin olmak için dilbilgisi açısından garip.
Matthew Frederick

13
Bunu sorduğunuz için teşekkürler - bu çok ilginç bir soru. Etrafa soracağım.
bbum

5
Bu özelliği istememe neden olan, ara sıra oluşan zorunlu gramer garipliği.
outis

1
Harika soru. Bir kenara, derleyicinin şu gibi adlandırılmış yöntemlerle herhangi bir sorunu yoktur: - (void) :(id)theMoney;veya - (void) :(id)obj1 :(id)obj2;. Dolayısıyla, iki nokta üst üste işaretlerinden başka hiçbir şey içermeyen seçiciler iyidir. ;-)
Ole Begemann

Yanıtlar:


111

Bu Brad Cox. Orijinal cevabım soruyu yanlış anladı. Gerçekten Hızlı'nın, bir tür sözdizimsel şeker değil, daha hızlı mesajlaşmayı tetikleyen sabit kodlanmış bir uzantı olduğunu varsaydım. Gerçek cevap Smalltalk'ın bunu desteklemediğidir, belki de ayrıştırıcısı (varsayılan) belirsizlikle baş edemediği için. OC'nin köşeli parantezleri herhangi bir belirsizliği ortadan kaldırsa da, Smalltalk'ın anahtar kelime yapısından ayrılmayı düşünmedim.


Teşekkürler Brad. Cevabınız hakkındaki yorumum aynıydı; SmallTalk'tan ayrılma dikkate alınmadı.
bbum

42

21 yıllık Objective-C programlama ve bu soru hiç aklıma gelmedi. Dil tasarımı göz önüne alındığında, derleyici haklıdır ve çalışma zamanı işlevleri yanlıştır ().

Yöntem adlarıyla birlikte eklenen bağımsız değişkenler kavramı, her zaman, en az bir bağımsız değişken varsa, son bağımsız değişkenin her zaman yöntem çağırma sözdiziminin son parçası olduğu anlamına gelir.

Bunu çok fazla düşünmeden, bahse girerim mevcut kalıbı zorlamayan bazı sözdizimsel bugabooslar vardır. En azından, derleyicinin, ifadelerle araya eklenmiş isteğe bağlı öğelere sahip herhangi bir sözdiziminin ayrıştırılması her zaman daha zor olacak şekilde yazılmasını zorlaştırır. Hatta bunu engelleyen bir uç durum bile olabilir. Kuşkusuz, Obj-C ++ bunu daha zor hale getirebilirdi, ancak bu, temel sözdizimi değiştirilinceye kadar yıllarca dile entegre edilmedi.

Objective-C'nin neden bu şekilde tasarlandığına gelince, cevabın, dilin orijinal tasarımcılarının aralıklı sözdiziminin bu son argümanın ötesine geçmesine izin vermediğini düşündüğünden şüpheleniyorum.

Bu en iyi tahmin. Onlardan birine soracağım ve daha fazlasını öğrendiğimde cevabımı güncelleyeceğim.


Brad Cox'a bunu sordum ve ayrıntılı olarak yanıt verirken çok cömert davrandı (Teşekkürler Brad !!):

O zamanlar Smalltalk'ı C'de olabildiğince çoğaltmaya ve bunu olabildiğince verimli bir şekilde yapmaya odaklanmıştım. Herhangi bir yedek döngü, sıradan mesajlaşmayı hızlı hale getirmeye başladı. Sıradan mesajlar olabildiğince hızlı olduğundan özel bir mesajlaşma seçeneği düşünülmemişti ("reallyFast?" [ Bbum: Örnek olarak 'doSomething: withSomething: reallyFast' kullanarak sordum ]). Bu, C proto-messager'ın assembler çıktısının elle ayarlanmasını içeriyordu, bu o kadar taşınabilirlik kabusuydu ki, hepsi olmasa da bazıları sonradan çıkarıldı. El hack'lenmiş mesajlaşmanın çok hızlı olduğunu hatırlıyorum; iki işlev çağrısının maliyeti hakkında; biri mesaj mantığına girmek ve geri kalanı bir kez orada yöntem aramaları yapmak için.
Statik yazım geliştirmeleri daha sonra Steve Naroff ve diğerleri tarafından Smalltalk'ın saf dinamik yazımının üstüne eklendi. Bununla sınırlı bir ilgim vardı.

Git Brad'in cevabını oku!


Sözdizimi bugaboos beni çok ilgilendiriyor.
outis

1
Bana öyle geliyor ki, iki nokta üst üste olmayan bir yöntem adı yığınınız varsa, bir ayrıştırma sorununuz var çünkü bunun yöntem adının bir parçası olup olmadığından emin olamazsınız.
NSResponder

2
Bir delege için Objective-C ile başladıktan sonra 21 yıldan çok daha kısa bir süre önce bir protokol tasarladığımda aklıma geldi. Normal model, ilk parametre olarak delege mesajını gönderen nesneyi sağlamaktır. ör -myObjectWithDelegate: (id) foo wantsYouToDoSomethingWith: (id) bar. Protokolde başka parametre gerektirmeyen bir yönteminiz varsa, bu, yöntem adlarında sarsıcı bir tutarsızlığa yol açar. Örnek için NSTableViewDataSource'a bakın. Bir yöntem, diğerlerinin hepsinin hoş ve düzgün modelini izlemez.
JeremyP

21

Bilginiz olsun, çalışma zamanı aslında seçicilerle ilgilenmez, herhangi bir C dizesi geçerlidir, bunun gibi bir seçici de yapabilirsiniz: "== + === + ---__-- ¨¨¨¨ ¨ ^ :::::: "hiçbir argüman olmadan çalışma zamanı kabul eder, derleyici kabul edemez veya ayrıştırmak imkansızdır. Seçiciler söz konusu olduğunda kesinlikle akıl sağlığı kontrolü yoktur.


7
+1 Bunu önerdiğin için tamamen deli olduğunu düşündüm, ama haklısın. İnanmayanlarınız için: pastie.org/1388361
Dave DeLong

6

Smalltalk'ta da mevcut olmadıkları için Objective-C'de desteklenmediklerini varsayıyorum. Ancak bunun düşündüğünüzden farklı bir nedeni var: onlara ihtiyaç yok. İhtiyaç duyulan şey, 0, 1, 2, 3, ... argümanlı yöntemler için destektir. Her argüman sayısı için, onları çağırmak için zaten çalışan bir sözdizimi vardır. Başka bir sözdizimi eklemek sadece gereksiz kafa karışıklığına neden olur.

Çok kelimeli parametresiz seçiciler istiyorsanız, neden tek bir ekstra kelime ile durasınız? O zaman bunu sorabilirsin

 [axolotl perform selector: Y with object: Y]

ayrıca desteklenir (yani bir seçici, bir dizi iki nokta üst üste ve bir parametre ile ve diğerleri değil) bir kelime dizisidir. Bu mümkün olsa da, kimsenin buna değeceğini düşünmediğini varsayıyorum.


1
"Gerekli değiller" argümanını düşünmüştüm, ama bununla ilgilenmedim. Güncellenen soru bunu daha net hale getiriyor. Boşluklar ve deve durumu arasındaki fark, son, parametresiz bir bileşen ile doğal dil ifadelerini yeniden yazma ve yeniden konumlandırma parametreleri arasındaki farktan daha az olduğundan, rastgele seçici bileşenlerin parametre almamasına izin vermek, yazılabilirlik açısından daha az şey sunar (her ikisi de yapılmalıdır) ObjC ile olduğu gibi).
outis

Ayrıca, keyfi parametresiz bileşenlere izin vermek, anahtar kelime çarpışmaları olasılığını artırır ve özellikle C ++ ve ObjC'yi karıştırırken ( andve orbelirli tökezleyen bloklar olur) ad çözümlemesini karmaşıklaştırır . Bu, birden çok kelimeden oluşma eğiliminde olacağından, bir yöntem adının yalnızca son bileşeninin parametreye sahip olmamasına izin verilseydi çok daha az olur.
outis
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.