Ereditarietà multipla Objective-C


88

Ho 2 classi, una include il metodo A e l'altra include il metodo B. Quindi in una nuova classe ho bisogno di sovrascrivere i metodi methodA e methodB. Allora come ottengo l'ereditarietà multipla nell'obiettivo C? Sono un po 'confuso con la sintassi.

Risposte:


136

Objective-C non supporta l'ereditarietà multipla e non ne hai bisogno. Usa composizione:

@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

Ora devi solo richiamare il metodo sull'ivar pertinente. È più codice, ma semplicemente non c'è ereditarietà multipla come caratteristica del linguaggio in Object-C.


8
La composizione è molto spesso un approccio migliore da adottare rispetto all'ereditarietà, soprattutto se si eseguono molti test unitari sul codice. Offre molta più flessibilità in quanto puoi facilmente sostituire le implementazioni senza ridefinire la classe stessa. Particolarmente utile quando si desidera, ad esempio, scambiare ClassA e ClassB con oggetti fittizi. Anche in fase di runtime la sostituzione delle implementazioni (ad esempio FTPFileStore vs LocalFileStore) diventa più pulita con la composizione. Ciò non significa che l'ereditarietà non abbia il suo posto, ma la necessità di eredità multipla suggerirebbe di ripensare al mio progetto;)
d11wtq

1
Non lo capisco. Non è necessario creare un'istanza ClassAe ClassB? Fa chiamando methodA:in MyClassqualche modo chiamare automaticamente methodA:su ClassA?
zakdances il

1
No, ma puoi comunque condividere il comportamento tramite il passaggio di messaggi, nel modo in cui OOP doveva funzionare originariamente. Se non salti immediatamente a pensare di aver bisogno dell'ereditarietà e invece prendi in considerazione una soluzione che utilizza la composizione, scoprirai che inizi a strutturare i tuoi programmi in un modo più gestibile. Ovviamente ObjC ha un'eredità di base per i casi in cui è corretto usarlo.
d11wtq


1
d11wtq, ottima risposta! Inoltre, l'inoltro dei messaggi consente di saltare il passaggio di reimplementazione del metodoA e del metodoB. I messaggi possono essere inoltrati automaticamente agli oggetti appropriati con un po 'di lavoro. developer.apple.com/library/mac/documentation/Cocoa/Conceptual/…
arsenius

3

Questo è il modo in cui codice singletonPattern come "genitore". Fondamentalmente ho usato una combinazione di protocollo e categoria.

L'unica cosa che non posso aggiungere è un nuovo "ivar", tuttavia, posso spingerlo con l'oggetto associato.

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

}

Ogni volta che voglio che una classe "erediti" questo BGSuperSingleton, faccio semplicemente:

#import "NSObject+singleton.h"

e aggiungi @interface MyNewClass () <BGSuperSingleton>


2
Le categorie non sono eredità multipla. Sono un modo per collegare metodi / funzioni a una classe già esistente. L'ereditarietà multipla consente a una terza classe di essere una combinazione di una O PIÙ classi (comprese le variabili). Mi piacciono le categorie. Le categorie sono molto utili. Ma NON sono eredità multipla.
Lloyd Sargent

Ma una sottoclasse di UIViewController può anche "supportare", in questo caso, il pattern singleton dovrei desiderare.
Septiadi Agus

Tecnicamente tutti gli NSManagedObject "possono ora chiamare" [obj singleton]. Ho impostato quelli che desidero con il supporto del protocollo. Buono come eredità multipla in ogni caso. Questo è solo se voglio che la classe figlia supporti sia l'interfaccia che l'implementazione del genitore. Se solo l'implementazione, ovviamente, la composizione è la strada da percorrere.
Septiadi Agus

La semplice aggiunta del protocollo come <BGSuperSingleton> non rende le classi quindi in grado di chiamare il metodo "singleton". Devi ancora implementarlo ...
CommaToast

-4

Conosci i protocolli, i protocolli sono il modo per implementare l'ereditarietà multipla


12
+1 "Per acquisire somiglianze tra classi che non sono correlate gerarchicamente." developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/…
pokstad

7
In questo caso, dove entrambi i metodi verranno sovrascritti, i protocolli faranno il trucco. In altri casi, quando si desidera utilizzare l'ereditarietà per riutilizzare il codice, i protocolli non sarebbero utili. Tuttavia questo di solito può essere risolto lasciando che le classi superclasse ereditino l'una dall'altra, o combinandole, di solito c'è un modo per farlo bene se una sottoclasse condivide effettivamente il codice con 2 classi.
jake_hetfield

puoi combinare il protocollo con una categoria o una composizione.
Septiadi Agus

-1 perché i protocolli non esistono affatto per l'ereditarietà multipla. Allo stesso modo JAVA, Interfacesnon devono fornire o imitare l'ereditarietà multipla.
cartello estivo

1
@FreeAsInBeer Dalla documentazione di Apple Un protocollo dichiara un'interfaccia programmatica che qualsiasi classe può scegliere di implementare. I protocolli consentono a due classi lontanamente imparentate per eredità di comunicare tra loro per raggiungere un determinato obiettivo. Offrono quindi un'alternativa alla sottoclasse . Come puoi vedere Apple utilizza esplicitamente la sottoclasse, ovvero l'ereditarietà. Forse Nikesh includendo questo nella sua risposta sarebbe utile per chiarire la sua argomentazione
Honey,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.