Pergunta

Em Ruby, há Módulos e você pode estender uma classe "misturando-em" o módulo.

module MyModule
  def printone
    print "one" 
  end
end

class MyClass
  include MyModule
end

theOne = MyClass.new
theOne.printone 
>> one

Em objective-C, eu acho que eu tenho um conjunto de métodos comuns que eu quero um número de Classe para "herdar".De que outro modo eu posso conseguir isso sem a criação de uma classe comum e derivando-se todos de que classe comum?

Foi útil?

Solução

Editar:alterações adicionado porque algumas pessoas acham que eu sou o responsável pelas limitações de objective-C.

Resposta curta:você não pode.Objective-C não tem o equivalente a mixins do Ruby.

Um pouco menos de resposta curta:Objective-C tem algo com aquele que é considerado o mesmo sabor:protocolos.Protocolos (Interfaces em outras línguas), são uma forma de definir um conjunto de métodos de uma classe que adota protocolos que está comprometendo-se a implementar.Um protocolo não fornece uma implementação embora.Essa limitação impede o uso de protocolos como um equivalente exato para mixins do Ruby.

Ainda menos de resposta curta: No entanto, o objective-C de tempo de execução tem uma exposto API que permite que você jogue com as características dinâmicas da linguagem.Em seguida, você pisar fora da linguagem, mas você pode ter protocolos com implementações de padrão (também chamados de protocolos concretos).Vladimir resposta mostra uma forma de fazer isso.Nesse ponto, parece-me que você obter mixins do Ruby tudo bem.

No entanto, eu não tenho certeza eu recomendaria fazer isso.Na maioria dos casos, outros padrões de caber a conta sem jogos, com tempo de execução.Por exemplo, você pode ter um sub-objeto que implemente o misto no método (tem-um em vez de é um).Jogando com o tempo de execução é OK, mas tem 2 problemas:

  • Você tornar o código menos legível, pois ela requer que os leitores sabem muito mais do que o idioma.Claro que você pode (e deve) fazer comentários, mas lembre-se que qualquer necessárias comentário pode ser visto como uma implementação defeito.

  • Você depende de que a implementação da linguagem.Com certeza, plataformas da Apple são de longe as mais comuns para Objective-C, mas não se esqueça de Cocotron ou GnuStep (ou Etoilé), que têm diferentes tempos de execução, que pode ou não ser compatível com o Apple no que diz respeito.

Como uma nota lateral, eu estado abaixo que categorias não é possível adicionar estado (variáveis de instância) de uma classe.Utilizando a API de tempo de execução, você pode levantar essa limitação também.Isso está além do escopo da sua resposta, no entanto.

Resposta longa:

Dois objective-C características olhar como possíveis candidatos:categorias e protocolos.As categorias não são realmente a escolha certa aqui, se eu entendi a pergunta corretamente.O direito de recurso é um protocolo.

Deixe-me dar um exemplo.Suponha que você queira um monte de suas aulas para ter uma habilidade específica chamado de "cantar".Em seguida, você define um protocolo:

@protocol Singer
    - (void) sing;
@end

Agora você pode declarar que qualquer de suas próprias classes adota o protocolo da seguinte forma:

@interface Rectangle : Shape <Singer> {
    <snip>
@end

@interface Car : Vehicle <Singer> {
    <snip>
@end

Ao declarar que adotam o protocolo se comprometem a implementar a sing o método.Por exemplo:

@implementation Rectangle

- (void) sing {
    [self flashInBrightColors];
}

@end

@implementation Car

- (void) sing {
    [self honk];
}

@end

Em seguida, você usar essas classes, por exemplo, como este:

void choral(NSArray *choir) // the choir holds any kind of singer
{
    id<Singer> aSinger;
    for (aSinger in choir) {
        [aSinger sing];
    }
}

Observe que os cantores na matriz não precisa ter uma superclasse comum.Observe também que uma classe pode ter apenas uma superclasse, mas muitos protocolos adotados.De notar, finalmente, que tipo de verificação é feito pelo compilador.

Em efeito, o protocolo de mecanismo de herança múltipla utilizado para o mixin padrão.Que herança múltipla é bastante limitada devido a um protocolo não pode adicionar novas variáveis de instância de uma classe.Um protocolo de apenas descreve uma interface pública adotantes devem implementar.Ao contrário do Ruby módulos que ele não contém uma implementação.

Que é mais do mesmo.Vamos mencionar categorias no entanto.

Uma categoria é declarada entre parênteses em ângulo, mas entre parênteses.A diferença é que uma categoria pode ser definido para uma classe existente para expandi-lo sem subclassificação ele.Você pode até mesmo fazê-lo para uma classe de sistema.Como você pode imaginar, é possível a utilização de categorias para implementar algo semelhante a mixin.E eles foram usados por um longo período de tempo, geralmente, como categoria para NSObject (o típico raiz da hierarquia de herança), a tal ponto que eles foram chamados de "informal" protocolos.

É informal porque 1 - nenhum tipo de verificação é feito pelo compilador, e 2 - implementar o protocolo de métodos é opcional.

Não há necessidade, hoje, de usar categorias como protocolos, especialmente porque o formal de protocolos pode agora declarar que alguns dos seus métodos são opcionais com a palavra-chave @optional ou necessária (o padrão) com @required.

Categorias ainda são úteis para adicionar algum domínio específico do comportamento de uma classe existente. NSString é um alvo comum para isso.

É também interessante ressaltar que a maioria (se não todos) dos NSObject as instalações são, na verdade, declarada em um NSObject o protocolo.Isso significa que ele não é realmente convincente para usar NSObject como uma superclasse comum para todas as classes, embora este ainda é feito comumente por razões históricas, e bem...porque não há nenhuma desvantagem para fazê-lo.Mas algumas classes de sistema, tais como NSProxy, são não NSObject.

Outras dicas

Plugue sem vergonha: ObjectivEmixin

Aproveita a capacidade do Objective-C Runtime de adicionar métodos a uma classe em tempo de execução (em oposição a categorias, que são apenas com tempo de compilação). Confira, funciona muito bem e de maneira semelhante às Mixins de Ruby.

Você pode literalmente misturar o código usando #include. Isso não é aconselhável e é contra todas as religiões no Objective-C, no entanto, funciona perfeitamente.

Por favor, não faça isso no código de produção.

Por exemplo, no arquivo:

Mixinmodule.header (não deve ser compilado ou copiado para o alvo)

-(void)hello;

Mixinmodule.body (não deve ser compilado ou copiado para o alvo)

-(void)hello{
    NSLog(@"Hello");
}

na aula de mixin:

@interface MixinTest : NSObject
#include "MixinModule.header"
@end

@implementation MixinTest
#include "MixinModule.body"
@end

Caso de uso:

#import <Foundation/Foundation.h>

int main(int argc, const char * argv[]){
    @autoreleasepool {
        [[[MixinTest new] autorelease] hello];
    }
    return 0;
}

Por favor, não faça isso no código de produção.

Esta é a minha opinião sobre a implementação do Mixins no Objective-C, sem usar o tempo de execução Objective-C diretamente. Talvez seja útil para alguém: https://stackoverflow.com/a/19661059/171933

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top