2011-12-28 16 views
9

iOS Programlama kitabının ikinci bölümünde, Joe Conway alt sınıflandırma durumunda sınıf yöntemlerinde 'kendini' kullanmayı açıklar. Bu kavramı anlıyorum ve alt sınıflama konusunda bir sorum var.Bir alt sınıftaki bir Objective-C'deki sınıf yöntemini düzgün bir şekilde nasıl geçersiz kılarım?

Amaç: Biz kimin sınıf yöntemi + randomPossession şöyle bir bulundurmak sınıfını yarattı:

+(id)randomPossession 
{ 
NSArray *randomAdjectiveList = [NSArray arrayWithObjects:@"Fluffy", @"Rusty", @"Shiny", nil]; 
NSArray *randomNounList = [NSArray arrayWithObjects:@"Bear", @"Spork", @"Mac", nil]; 

unsigned long adjectiveIndex = rand() % [randomAdjectiveList count]; 
unsigned long nounIndex = rand() % [randomNounList count]; 

NSString *randomName = [NSString stringWithFormat:@"%@ %@", [randomAdjectiveList objectAtIndex:adjectiveIndex], [randomNounList objectAtIndex:nounIndex]]; 

int randomValue = rand() % 100; 

NSString *randomSerialNumber = [NSString stringWithFormat:@"%c%c%c%c%c", 
           '0' + rand() % 10, 
           'A' + rand() % 10, 
           '0' + rand() % 10, 
           'A' + rand() % 10, 
           '0' + rand() % 10]; 

Possession *newPossession = [[self alloc] initWithPossessionName:randomName valueInDollars:randomValue serialNumber:randomSerialNumber]; 

return [newPossession autorelease]; 
} 

ben dönüş değeri gerçekten tip id olmalıdır farkındayım öyle ki id newPossession = ...

Ben Topla sınıflandırma ve yeni Ivar, markası, şöyle ben BallGlove içinde + randomPossession overrode bir NSString *

dahil bir sınıf olarak adlandırılan BallGlove oluşturuldu:

+(id)randomPossession 
{ 
BallGlove *myGlove = [super randomPossession]; 

NSArray *brandNames = [NSArray arrayWithObjects:@"Rawlings", @"Mizuno", @"Wilson", nil]; 

unsigned long randomNameIndex = rand() % [brandNames count]; 

[myGlove setBrandName:[brandNames objectAtIndex:randomNameIndex]]; 

NSLog(@"myGlove is of type class: %@", [self class]); 

return myGlove; 
} 

Sorum şu: Bu sınıf yönteminin, topluluk tarafından uygun ve kabul edilebilir şekilde geçersiz kılındığı yöntem (örn. bir değişkende süper uygulamayı yakalayarak -init formatına paralel olarak, değişkeni buna göre manipüle eder ve sonra geri gönderir? Çıktılarım, döndürülen nesnenin bir BallGlove örneğidir, ancak kabul edilebilir uygulamaya ilgi duyuyordum. Şimdiden teşekkürler.

cevap

0

Teknik olarak sorun değil. Bununla birlikte, bir alternatif önerebilirim. Zaten temel sınıfınızda belirlenmiş bir public başlatıcınız varsa (zaten bu fabrika sınıfı yöntemini oluşturmak ve çağırmak isteyebilirsiniz) ve alt sınıflarınızın sınıfındaki bu çok başlatıcıyı (veya alt sınıfınızdan yeni bir tane bile) kullanabilirsiniz. yöntem.

Değil çok daha kod, ama bence daha kolay takip ediyor ve geleceğe dönük. Başlatıcı aynı zamanda bir noktada kullanışlı olabilir, ancak elbette her uygulama için bir çözüm değildir.

+0

+ randomPossession aslında belirtilen başlatıcıyı çağırır. Sınıf yöntemi, bu başlatıcı için "rasgele" değerler de oluşturur. Eğer önerdiğini düşündüğüm şeyi yaparsam, override sınıf yöntemindeki (rasgele) "rastgele" değerlerin kodunu çoğaltmalı ve BallGlove sınıfının yeni bir başlatıcısını çağırmak için belirlenen başlatıcıyı geçersiz kılmalıydım. ek iVar bilgilerimi ekle. Genel anlamda zararlı önerdiğim gibi sınıf yöntemini neden geçersiz kılıyor? Başlatıcıları zincirlemek mümkün değil mi? –

+0

Bunun çok çirkin olduğunu düşünmüyorum - sadece çok yaygın bir model değil. Sorunun kendisi bunun için iyi bir göstergedir. :) Alt sınıflama ile biraz belirsiz olan bir şey yöntemin adıdır ve iyi adlandırma objektif-c hakkında en iyi şeylerden biridir. Bu durumda, bir yöntem + randomBallGlove, geçersiz kılmaktan daha iyi olabilir. – Eiko

+0

Bunun yerine, istenen özel uygulamaya ek olarak + randomPossession uygulamasının kullanılmasını içeren + randomBallGlove adlı bir sınıf yöntemi oluşturduğumu mu söylüyorsunuz? Bana uyar. + RandomPossession için hala sahip olma alt sınıflarına sunulmak için ne önerirsiniz? yöntemi geçersiz kılın ve + randomBallGlove'nin bir yönlendirme yönlendirme kullanmasını sağlayın? Bu genellikle bu tür olayların normal protokolü mü?Bu örneğin gerçekte varolmayan olabileceğini biliyorum, sadece öğrendim ve olayın gerçekleştiği yerde uygulamayı kabul ettiğim için merak ediyorum. Yardım ettiğin için teşekkür ederim! –

1

Evet, başlatmanızı böyle yapmak kabul edilebilir. Aslında çoğu durumda böyle yapılır. Demek istediğim, ilk etapta bir süper sınıftan miras almanın sebebi budur. Süper sınıfta bulunanlara ek olarak bir şeyler istiyorsun. Yani, miras alınan sınıfa özgü olan her şeye kod eklersiniz ve bu şekilde yapılmalıdır.

BallGlove nesnesinin nasıl başlatılmasını istediğinizi de kalıtsal yönteminizi nasıl tanımladığınıza dair bir faktör olduğunu düşünüyorum. Soru, Possession init'i çağırmak veya BallGlove init'i çağırmaktan kaynaklanır (Sınıf örneğini oluşturmak, sınıf yöntemini kullanmanın tek adresi değil). Yani sizin nesnelerinizi yaratmanın mantığına, yani ne kadar iyi BallGlove nesnesini tanımladığınızı anlatıyorsunuz-sınıf yönteminizin bunu BallGlove nesne ölçütlerine uygun şekilde tanımladığından ve genel Possession nesnesine dönüşmediğinden emin oluyorsunuz. Cevabım, doğru bir şekilde uygulayabiliyorsanız, paralel bir sınıf yöntemleri kullanarak kabul edilebilir. Eğer süper sınıfta tip Possession arasında dönen eğer id herhangi sınıf türü

+0

Cevabınız için teşekkür ederiz. Ancak bu soruya gerçekten cevap vermedi. Soru, sınıf yöntemlerini geçersiz kılma biçiminde ele alınmıştır. Bir alt sınıf için bir kolaylık yöntemi oluşturmanın gerekliliği dışında, sınıf yöntemini geçersiz kılmanın bir nedeninden emin değilim. Öyle olduğu gibi, henüz bir şey görmedim. Kullandığım formatın uygun olduğunu doğrulayan herhangi bir örnek var mı? –

+0

@BrianPalma Üzgünüm. Belki de doğru cevap vermedim. Sınıf yöntemleri için başlatıcılarla aynı şekilde neden kabul edilemediğini anlamıyorum. Çalıştığım şekilde, sınıf yöntemleri init yöntemlerini çağırmak, bazı kodları gerçekleştirmek ve yaptığınız şeyden bir otomatikleştirilmiş sürümü döndürmek eğilimindedir. Biçiminizi doğrulamak için örnekler olup olmadığını bilmiyorum, ancak bunun dışında ortaya çıkabilecek herhangi bir sorun göremiyorum. Bazı örnek kodları kontrol edip size geri dönelim. – MadhavanRP

2

Yep bir nesneye işaret edebilir, çünkü

Ayrıca önemli değil, bunu yapmak için mükemmel mantıklı bir yoldur. Sınıf yöntemleri ve normal yöntemler arasında özellikle farklı bir şey yoktur - sadece biri bir sınıf tarafından gerçekleştirilirken diğeri bir örnek tarafından gerçekleştirilir.

2

Bir sınıf yöntemini geçersiz kıldığınız an, onu süper uygulamanın yardımıyla veya onsuz gerçekleştirmeye karar verebilirsiniz. Bu tamamen size kalmış. Overiding init tamamen farklı bir öyküdür, sadece bir örnek yöntem olduğu için değil, onunla bağlantılı bir sözleşmesi/sözleşmesi olduğu için. Örneğin, Liskov Subtitution ilkesinin ihlal edilmemesi gerektiğini aklınızdan çıkarmayın.

Sınıf yöntemini geçersiz kılan bir tasarım kokusu olsa da, sınıf yöntemini geçersiz kıldınız. Objective-C'de çok iyi olmasına rağmen, başka dillerde değil ve çok iyi bir nedenden dolayı. Bir kavram olarak polimorfizm, birbirinin yerine geçecek şekilde kullanılabilecek örneklere daha iyi bağlıdır, oysa sınıf metotları kullanarak kavramı bozar (yani gerçek bir altyazı yoktur).Zeki, ama sezgisel ve esnek değil.

+0

Cevabınız için teşekkür ederiz. Aşağıda bahsettiğim gibi, bir alt sınıftaki bir sınıf yöntemini geçersiz kılmanın herhangi bir kullanımının, bir kolaylık yönteminde daha az kodun dışında olduğunun farkında değilim. Bu noktada, böyle bir niyetim yok. Durumun ortaya çıkması durumunda sadece doğru uygulama konusunda merak ettim. –

+0

@BrianPalma: "Uygunluk yöntemleri" dışındaki sınıf yöntemlerini geçersiz kılacak nedenler var. Örneğin, NSView'ın 'defaultMenu' ve' requireConstraintBasedLayout' sınıfı yöntemleri yalnızca geçersiz kılınmak için var. – Chuck

+0

@Chuck Üzgünüm, sanırım yanlış konuştum ya da çok yeniyim! Model nesneleri açısından "kolaylık yöntemleri" demek istiyorum. IOS ve OS X’de tamamen geçersiz kılınmış ve [super someClassMethodHere] gerektiren bir sınıf yöntemi olduğunu anlıyorum; –

İlgili konular