Dziedziczenie wielokrotne z celem C

88

Mam 2 klasy, jedna zawiera MethodA, a druga zawiera MethodB. Więc w nowej klasie muszę zastąpić metody MethodA i MethodB. Jak więc osiągnąć wielokrotne dziedziczenie w celu C? Jestem trochę zdezorientowany ze składnią.

Dilshan
źródło

Odpowiedzi:

136

Objective-C nie obsługuje dziedziczenia wielokrotnego i nie jest to potrzebne. Użyj kompozycji:

@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

Teraz wystarczy wywołać metodę na odpowiednim ivar. To więcej kodu, ale po prostu nie ma wielokrotnego dziedziczenia jako funkcji języka w celu-C.

d11wtq
źródło
8
Kompozycja jest bardzo często lepszym podejściem niż dziedziczenie, zwłaszcza jeśli wykonujesz wiele testów jednostkowych w kodzie. Zapewnia znacznie większą elastyczność, ponieważ można łatwo wymieniać implementacje bez ponownego definiowania samej klasy. Jest to szczególnie przydatne, gdy chcesz, powiedzmy, zamienić klasę A i B na pozorowane obiekty. Nawet w czasie wykonywania zamiana implementacji (np. FTPFileStore vs LocalFileStore) staje się czystsza dzięki kompozycji. Nie oznacza to jednak, że dziedziczenie nie ma swojego miejsca, ale potrzeba wielokrotnego dziedziczenia sugerowałaby, żebym ponownie przemyślał swój projekt;)
d11wtq
1
Nie rozumiem tego. Nie musisz tworzyć instancji ClassAi ClassB? Czy dzwoniąc methodA:na MyClassjakoś automatycznie zadzwoni methodA:na ClassA?
zakdances
1
Nie, ale nadal możesz udostępniać to zachowanie poprzez przekazywanie wiadomości, tak jak pierwotnie miało działać OOP. Jeśli nie od razu przejdziesz do myślenia, że ​​potrzebujesz dziedziczenia i zamiast tego rozważasz rozwiązanie wykorzystujące kompozycję, zobaczysz, że zaczniesz tworzyć struktury swoich programów w łatwiejszy do utrzymania sposób. Oczywiście ObjC ma podstawowe dziedziczenie w przypadkach, w których jego użycie jest poprawne.
d11wtq
1
d11wtq, świetna odpowiedź! Dodatkowo przekazywanie wiadomości pozwala na pominięcie kroku ponownego wdrażania metod MethodA i MethodB. Wiadomości mogą być automatycznie przekazywane do odpowiednich obiektów przy niewielkim nakładzie pracy. developer.apple.com/library/mac/documentation/Cocoa/Conceptual/…
arsenius
3

Tak koduję singletonPattern jako „rodzica”. Zasadniczo użyłem kombinacji protokołu i kategorii.

Jedyne, czego nie mogę dodać, to nowy "ivar", ale mogę go wcisnąć z powiązanym obiektem.

#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
{

}

Ilekroć chcę, aby klasa „odziedziczyła” ten BGSuperSingleton, po prostu robię:

#import "NSObject+singleton.h"

i dodaj @interface MyNewClass () <BGSuperSingleton>

Septiadi Agus
źródło
2
Kategorie nie są dziedziczone wielokrotnie. Są sposobem na przypisanie metod / funkcji do już istniejącej klasy. Dziedziczenie wielokrotne pozwala, aby trzecia klasa była kombinacją jednej lub WIĘCEJ klas (w tym zmiennych). Lubię kategorie. Kategorie są bardzo przydatne. Ale NIE są dziedziczeniem wielokrotnym.
Lloyd Sargent
Ale podklasa UIViewController może również "obsługiwać", w tym przypadku, pojedynczy wzorzec.
Septiadi Agus
Technicznie rzecz biorąc, wszystkie obiekty NSManagedObject "mogą teraz wywoływać" [obj singleton]. Ustawiam te, które chcę, przy wsparciu protokołu. W każdym razie tak dobre, jak wielokrotne dziedziczenie. Dzieje się tak tylko wtedy, gdy chcę, aby klasa podrzędna obsługiwała zarówno interfejs, jak i implementację rodzica. Jeśli tylko realizacja, to oczywiście kompozycja jest drogą do zrobienia.
Septiadi Agus
Samo dodanie protokołu, takiego jak <BGSuperSingleton>, nie powoduje, że klasy mogą następnie wywołać metodę „singleton”. Nadal musisz to zaimplementować ...
CommaToast
-4

Czy wiesz o protokołach, protokoły są sposobem implementacji wielokrotnego dziedziczenia

Nikesh K.
źródło
12
+1 „Aby uchwycić podobieństwa między klasami, które nie są hierarchicznie powiązane”. developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ ...
pokstad
7
W takim przypadku, gdy obie metody zostaną zastąpione, protokoły załatwią sprawę. W innych przypadkach, gdy chcesz użyć dziedziczenia do ponownego wykorzystania kodu, protokoły nie pomogą. Jednak zwykle można to rozwiązać, pozwalając klasom nadklasy dziedziczyć po sobie lub łącząc je. Zwykle jest sposób, aby to naprawić, jeśli podklasa faktycznie współdzieli kod z 2 klasami.
jake_hetfield
możesz połączyć protokół z kategorią lub kompozycją.
Septiadi Agus
-1, ponieważ w ogóle nie ma protokołów do wielokrotnego dziedziczenia. Podobnie w JAVA, Interfacesnie są do świadczenia lub naśladować wielokrotne dziedziczenie.
thesummersign
1
@FreeAsInBeer Z własnej dokumentacji Apple Protokół deklaruje interfejs programistyczny, który każda klasa może zaimplementować. Protokoły umożliwiają dwóm klasom odległym ze sobą spokrewnionym dziedziczeniem komunikowanie się ze sobą w celu osiągnięcia określonego celu. W ten sposób stanowią alternatywę dla podklas . Jak widać, Apple jawnie używa podklas, czyli dziedziczenia. Być może włączenie tego przez Nikesza do własnej odpowiedzi byłoby pomocne w wyjaśnieniu jego argumentu
Kochanie,