Objective-C çoklu kalıtım


88

Biri methodA'yı, diğeri de methodB'yi içeren 2 sınıfım var. Yani yeni bir sınıfta methodA ve methodB yöntemlerini geçersiz kılmam gerekiyor. Öyleyse C hedefinde çoklu mirasa nasıl ulaşırım? Sözdizimi ile biraz kafam karıştı.

Yanıtlar:


136

Objective-C çoklu kalıtımı desteklemez ve buna ihtiyacınız yoktur. Kompozisyonu kullanın:

@interface ClassA : NSObject {
}

-(void)methodA;

@end

@interface ClassB : NSObject {
}

-(void)methodB;

@end

@interface MyClass : NSObject {
  ClassA *a;
  ClassB *b;
}

-(id)initWithA:(ClassA *)anA b:(ClassB *)aB;

-(void)methodA;
-(void)methodB;

@end

Şimdi sadece ilgili ivar'daki yöntemi çağırmanız yeterlidir. Daha fazla kod, ancak amaç-C'de dil özelliği olarak çoklu kalıtım yoktur.


8
Kompozisyon, kalıtımdan çok daha iyi bir yaklaşımdır, özellikle de kod üzerinde çok fazla birim testi yaparsanız. Sınıfın kendisini yeniden tanımlamadan uygulamaları kolayca değiştirebileceğiniz için çok daha fazla esneklik sağlar. Örneğin ClassA ve ClassB'yi sahte nesnelerle değiştirmek istediğinizde özellikle kullanışlıdır. Çalışma zamanında bile takas uygulamaları (örneğin FTPFileStore vs LocalFileStore) kompozisyonla daha temiz hale gelir. Bu, mirasın yeri olmadığı anlamına gelmez, ancak çoklu mirasa duyulan ihtiyaç, tasarımımı yeniden düşünmemi önerebilir;)
d11wtq

1
Ben bunu anlamıyorum Eğer örneğini gerek yok ClassAve ClassB? Çağıran mu methodA:üzerinde MyClassnedense otomatik çağrı methodA:üzerine ClassA?
zakdances

1
Hayır, ancak davranışı, OOP'nin başlangıçta çalışması gerektiği gibi, mesaj iletme yoluyla paylaşabilirsiniz. Hemen kalıtıma ihtiyacınız olduğunu düşünmezseniz ve bunun yerine kompozisyon kullanarak bir çözüm düşünürseniz, programlarınızı daha sürdürülebilir bir şekilde yapılandırmaya başladığınızı göreceksiniz. Tabii ki ObjC, onu kullanmanın doğru olduğu durumlar için temel mirasa sahiptir.
d11wtq


1
d11wtq, harika yanıt! Ek olarak, mesaj yönlendirme, methodA ve methodB'yi yeniden uygulama adımını atlamanıza izin verir. Mesajlar, küçük bir çalışma ile otomatik olarak uygun nesnelere iletilebilir. developer.apple.com/library/mac/documentation/Cocoa/Conceptual/…
arsenius

3

SingletonPattern'i bu şekilde "ebeveyn" olarak kodluyorum. Temelde protokol ve kategori kombinasyonunu kullandım.

Ekleyemediğim tek şey yeni bir "ivar" ancak onu ilişkili nesneyle itebilirim.

#import <Foundation/Foundation.h>
@protocol BGSuperSingleton
+(id) singleton1;
+(instancetype)singleton;
@end

@interface NSObject (singleton) <BGSuperSingleton>

@end

static NSMutableDictionary * allTheSingletons;

+(instancetype)singleton
{
    return [self singleton1];
}
+(id) singleton1
{
    NSString* className = NSStringFromClass([self class]);

    if (!allTheSingletons)
    {
        allTheSingletons = NSMutableDictionary.dictionary;
    }

    id result = allTheSingletons[className];

    //PO(result);
    if (result==nil)
    {
        result = [[[self class] alloc]init];
        allTheSingletons[className]=result;
        [result additionalInitialization];
    }
    return result;
}

-(void) additionalInitialization
{

}

Bir sınıfın bu BGSuperSingleton'ı "miras almasını" istediğimde, sadece şunu yapıyorum:

#import "NSObject+singleton.h"

ve Ekle @interface MyNewClass () <BGSuperSingleton>


2
Kategoriler çoklu miras değildir. Zaten var olan bir sınıfa yönelik yöntemler / işlevler üzerinde çalışmanın bir yoludur. Çoklu miras, üçüncü bir sınıfın bir VEYA DAHA FAZLA sınıfın (değişkenler dahil) bir kombinasyonu olmasına izin verir. Kategorileri severim. Kategoriler çok kullanışlıdır. Ancak bunlar çoklu miras DEĞİLDİR.
Lloyd Sargent

Ancak UIViewController'ın bir alt sınıfı da, bu durumda, tekli model istersem "destekleyebilir".
Septiadi Agus

Teknik olarak tüm NSManagedObject "artık" [obj singleton] 'ı çağırabilir. Protokol desteği ile dilediklerimi belirledim. Zaten çoklu miras kadar iyi. Bu, yalnızca alt sınıfın ebeveynin hem arabirimini hem de uygulamasını desteklemesini istiyorsam. Eğer sadece uygulama ise, o zaman açıkça kompozisyon gidilecek yoldur.
Septiadi Agus

<BGSuperSingleton> gibi bir protokol eklemek, sınıfların "singleton" yöntemini çağırmasını sağlamaz. Yine de uygulamanız gerekiyor ...
CommaToast

-4

Protokoller hakkında bilginiz var mı, protokoller çoklu kalıtımı gerçekleştirmenin yoludur


12
+1 "Hiyerarşik olarak ilişkili olmayan sınıflar arasındaki benzerlikleri yakalamak için." developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/…
pokstad

7
Her iki yöntemin de geçersiz kılınacağı bu durumda, protokoller hile yapacak. Diğer durumlarda, kodu yeniden kullanmak için mirası kullanmak istediğinizde, protokoller yardımcı olmaz. Bununla birlikte, bu genellikle, sınıfların üst sınıfların birbirlerinden miras almasına izin vererek veya bunları birleştirerek çözülebilir, eğer bir alt sınıf aslında 2 sınıfla kod paylaşıyorsa, genellikle bunu doğru bir şekilde yapmanın bir yolu vardır.
jake_hetfield

protokolü bir kategori veya kompozisyon ile birleştirebilirsiniz.
Septiadi Agus

-1 çünkü Protokoller birden fazla kalıtım için orada değildir. Benzer şekilde JAVA, Interfacesçoklu kalıtım sağlamak veya taklit etmek için değildir.
thesummersign

1
@FreeAsInBeer Apple'ın kendi belgelerinden Bir protokol, herhangi bir sınıfın uygulamayı seçebileceği programlı bir arabirimi bildirir. Protokoller, kalıtımla uzaktan ilişkili iki sınıfın belirli bir hedefi gerçekleştirmek için birbirleriyle iletişim kurmasını mümkün kılar. Bu nedenle , alt sınıflamaya bir alternatif sunarlar . Gördüğünüz gibi, Apple açıkça alt sınıflandırma, yani miras alma kullanıyor. Belki de Nikesh kendi cevabına bunu dahil ederek argümanını netleştirmeye yardımcı olabilir
Honey
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.