Herança múltipla de Objective-C

88

Eu tenho 2 classes, uma inclui o métodoA e a outra inclui o métodoB. Portanto, em uma nova classe, preciso substituir os métodos methodA e methodB. Então, como faço para obter herança múltipla no objetivo C? Estou um pouco confuso com a sintaxe.

Dilshan
fonte

Respostas:

136

Objective-C não oferece suporte a herança múltipla e você não precisa dela. Use composição:

@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

Agora você só precisa invocar o método no ivar relevante. É mais código, mas simplesmente não há herança múltipla como um recurso de linguagem em objetivo-C.

d11wtq
fonte
8
A composição geralmente é uma abordagem melhor do que a herança, especialmente se você fizer muitos testes de unidade no código. Ele oferece muito mais flexibilidade, pois você pode facilmente trocar as implementações sem redefinir a própria classe. Particularmente útil quando você deseja, digamos, trocar ClassA e ClassB por objetos fictícios. Mesmo em tempo de execução, a troca de implementações (por exemplo, FTPFileStore vs LocalFileStore) torna-se mais limpa com a composição. Isso não significa que a herança não tem seu lugar, mas a necessidade de herança múltipla sugere que eu repensar meu projeto;)
d11wtq
1
Eu não entendo isso. Você não precisa instanciar ClassAe ClassB? Faz chamar methodA:em MyClassalguma forma chamar automaticamente methodA:em ClassA?
zakdances
1
Não, mas você ainda pode compartilhar o comportamento por meio da troca de mensagens, da maneira que o OOP deveria funcionar originalmente. Se você não começar imediatamente a pensar que precisa de herança e, em vez disso, considerar uma solução usando composição, verá que começou a estruturar seus programas de uma maneira mais sustentável. É claro que ObjC tem herança básica para os casos em que é correto usá-lo.
d11wtq
1
d11wtq, ótima resposta! Além disso, o encaminhamento de mensagens permite que você ignore a etapa de reimplementação do método A e do método B. As mensagens podem ser encaminhadas automaticamente para objetos apropriados com apenas um pouco de trabalho. developer.apple.com/library/mac/documentation/Cocoa/Conceptual/…
arsenius
3

É assim que codifico singletonPattern como "um pai". Basicamente, usei uma combinação de protocolo e categoria.

A única coisa que não posso adicionar é um novo "ivar", no entanto, posso empurrá-lo com o objeto associado.

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

}

Sempre que quero que uma classe "herde" este BGSuperSingleton, eu simplesmente faço:

#import "NSObject+singleton.h"

e adicione @interface MyNewClass () <BGSuperSingleton>

Septiadi Agus
fonte
2
As categorias não são herança múltipla. Eles são uma forma de agregar métodos / funções a uma classe já existente. A herança múltipla permite que uma terceira classe seja uma combinação de uma OU MAIS classes (incluindo variáveis). Gosto de categorias. As categorias são muito úteis. Mas eles NÃO são herança múltipla.
Lloyd Sargent
Mas uma subclasse de UIViewController também pode "suportar", neste caso, o padrão singleton, se eu desejar.
Septiadi Agus
Tecnicamente, todos os NSManagedObject "agora podem chamar" [obj singleton]. Eu defino aqueles que desejo com o apoio do protocolo. Tão bom quanto a herança múltipla de qualquer maneira. Isso é apenas se eu quiser que a classe filha dê suporte à interface e à implementação do pai. Se apenas a implementação, obviamente a composição é o caminho a percorrer.
Septiadi Agus de
Apenas adicionar o protocolo como <BGSuperSingleton> não torna as classes capazes de chamar o método "singleton". Você ainda tem que implementá-lo ...
CommaToast
-4

Você conhece os protocolos, os protocolos são a maneira de implementar a herança múltipla

Nikesh K
fonte
12
+1 "Para capturar semelhanças entre classes que não estão hierarquicamente relacionadas." developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/…
pokstad
7
Nesse caso, onde ambos os métodos serão substituídos, os protocolos farão o trabalho. Em outros casos, quando você deseja usar a herança para reutilizar o código, os protocolos não ajudam. No entanto, isso geralmente pode ser resolvido permitindo que as superclasses de classes herdem umas das outras, ou combinando-as, geralmente há uma maneira de acertar se uma subclasse realmente compartilhar código com 2 classes.
jake_hetfield
você pode combinar protocolo com uma categoria ou composição.
Septiadi Agus
-1 porque os protocolos não existem para herança múltipla. Da mesma forma JAVA, Interfacesnão devem fornecer ou simular herança múltipla.
thesummersign
1
@FreeAsInBeer Da própria documentação da Apple Um protocolo declara uma interface programática que qualquer classe pode escolher implementar. Os protocolos possibilitam que duas classes distantemente relacionadas por herança se comuniquem entre si para atingir um determinado objetivo. Eles, portanto, oferecem uma alternativa à subclasse . Como você pode ver, a Apple está usando explicitamente a subclasse, ou seja, a herança. Talvez Nikesh incluindo isso em sua própria resposta seja útil para esclarecer seu argumento
Honey