Pergunta

Pode alguém explicar-me a diferença entre categorias e herança em Objective C? Eu li a entrada na Wikipedia ea discussão sobre categorias não faz olhar diferente ao de herança. Eu também olhou para a discussão sobre o tema no livro "Open iPhone Desenvolvimento" e eu ainda não obtê-lo.

Foi útil?

Solução

Às vezes, herança apenas parece ser mais problemas do que vale a pena. Ele é usado corretamente quando você deseja adicionar algo a uma classe existente que é uma mudança no comportamento dessa classe.

Com uma categoria, você apenas deseja que o objeto existente para fazer um pouco mais. Como já foi dada, se você só quer ter uma classe string que a compressão de alças, você não precisa criar uma subclasse da classe string, você acabou de criar uma categoria que lida com a compressão. Dessa forma, você não precisa alterar o tipo das classes de cadeias que você já usa.

A pista está na restrição de que as categorias só adicionar métodos, você não pode adicionar variáveis ??a uma classe usando categorias. Se a classe precisa mais propriedades, então ele tem que ser uma subclasse.. (Edit: você pode usar o armazenamento associativo, creio eu)

As categorias são uma boa maneira de adicionar funcionalidades ao mesmo tempo em conformidade com um princípio de orientação a objetos a preferir a composição sobre a herança.

Editar janeiro 2012

As coisas mudaram agora. Com o compilador LLVM atual, eo, 64-bit tempo de execução moderno, você pode adicionar Ivars e propriedades para a classe extensões (não categorias). Isso permite manter Ivars privadas fora da interface pública. Mas, se você declarar propriedades para os Ivars, eles ainda podem ser acessados ??/ alterado através KVC, porque ainda não há tal coisa como um método particular em Objective-C.

Outras dicas

As categorias permitem que você adicione métodos para classes existentes. Então ao invés de subclasse NSData para adicionar seus novos métodos de criptografia funk, você pode adicioná-los diretamente para a classe NSData. Cada objeto NSData em seu aplicativo agora tem acesso a esses métodos.

Para ver como isso pode ser útil, olhada: CocoaDev

Uma das ilustrações favoritas de categorias Objective-C em ação é NSString. NSString é definido no âmbito Foundation, que não tem noção de exibições ou janelas. No entanto, se você usar um NSString em um aplicativo de cacau você notará que responde a mensagens como – drawInRect:withAttributes:.

AppKit define uma categoria para NSString que fornece métodos de desenho adicionais. A categoria permite que novos métodos a serem adicionados a uma classe existente, por isso estamos ainda lidando apenas com NSStrings. Se AppKit vez desenho implementado por subclasses teríamos que lidar com 'AppKitStrings' ou 'NSSDrawableStrings' ou algo parecido.

categorias permitem que você adicione métodos de aplicação ou específicas de domínio para classes existentes. Ela pode ser muito poderoso e conveniente.

Se você como um programador é dado um conjunto completo de código fonte para uma biblioteca de código ou aplicativo, você pode ir nozes e mudança o que você precisa para atingir seu objetivo de programação com esse código.

Infelizmente, isso nem sempre é o caso ou até mesmo desejável. Muitas vezes você recebe um kit binário biblioteca / objeto e um conjunto de cabeçalhos de se contentar com.

Em seguida, uma nova funcionalidade é necessária para uma classe que você poderia fazer um par de coisas:

  1. criar uma nova classe inteira em vez de uma classe de ações -. Replicar todas as suas funções e membros então reescrever todo o código para usar a nova classe

  2. criar uma nova classe de invólucro que contém a classe de ações como um membro (composição) e reescrever o código base para utilizar a nova classe.

  3. remendos binários da biblioteca para alterar o código (boa sorte)

  4. forçar o compilador para ver sua nova classe como o velho e espero que isso não depende de um certo tamanho ou local em pontos de entrada de memória e específicas.

  5. subclasse especialização - criar subclasses para adicionar funcionalidade e modificar o código do driver para usar a subclasse em vez - teoricamente deveria haver alguns problemas e se você precisa adicionar dados membros, é necessário, mas o consumo de memória será diferente. Você tem a vantagem de ter tanto o novo código e o código antigo disponível na subclasse e escolher qual usar, o método da classe base ou o método substituído.

  6. modificar a classe objc necessário, com uma definição categoria que contém métodos para fazer o que quiser e / ou substituir os velhos métodos nas classes de ações.

    Isso também pode corrigir erros na biblioteca ou customize métodos para novos dispositivos de hardware ou qualquer outra coisa. Não é uma panacéia, mas permite método de classe adicionando sem recompilar a classe / biblioteca que está inalterado. A classe original é o mesmo em código, tamanho da memória, e os pontos de entrada, de modo que aplicações legadas não quebrar. O compilador simplesmente coloca o novo método (s) no tempo de execução como pertencente a essa classe e substitui métodos com a mesma assinatura no código original.

    Por exemplo:

    Você tem uma classe Bing que saídas para um terminal, mas não a uma porta serial, e agora que é o que você precisa. (por algum motivo). Você tem Bing.h e libBing.so, mas não Bing.m no seu kit.

    A classe Bing faz todos os tipos de coisas internamente, você nem sequer sabe de tudo o que, você só tem a API pública no cabeçalho.

    Você é inteligente, para que criar uma categoria (SerialOutput) para a classe Bing.

    [Bing_SerialOutput.m]
    @interface Bing (SerialOutput)   // a category
    - (void)ToSerial: (SerialPort*) port ;
    @end
    
    @implementation Bing (SerialOutput)
    - (void)ToSerial: (SerialPort*) port 
    {
    ... /// serial output code ///
    }
    @end
    

    Os obriga compilador para criar um objeto que pode ser ligado com a sua aplicação eo tempo de execução agora sabe que Bing responde a @selector (ToSerial :) e você pode usá-lo como se a classe Bing foi construído com esse método. Você não pode adicionar membros de dados únicos métodos e este não foi concebido para criar tumores gigantes de código anexado a classes base, mas ele tem suas vantagens sobre línguas estritamente digitados.

Eu acho que algumas dessas respostas, pelo menos, apontam para a ideia de que a herança é uma forma mais pesada de adicionar funcionalidade a uma classe existente, enquanto categorias são mais leves.

A herança é usado quando você está criando uma nova hierarquia de classes (todos os sinos e assobios) e sem dúvida traz um monte de trabalho quando escolhido como o método de adicionar funcionalidade às classes existentes.

Como alguém aqui colocá-lo ... Se você estiver usando herança para adicionar um novo método por exemplo, para NSString, você tem que ir e mudar o tipo que você está usando em qualquer outro código onde você quer usar este novo método. Se, no entanto, você usa categorias, você pode simplesmente chamar o método em tipos NSString existente, sem subclassificação.

Os mesmos fins pode ser conseguido com qualquer um, mas categorias parecem nos dar uma opção que é mais simples e requer menos manutenção (provavelmente).

Alguém sabe se existem situações em que as categorias são absolutamente necessárias?

A Categoria é como um mixin: um módulo em Ruby, ou um pouco como uma interface em Java. Você pode pensar nisso como "métodos nus". Quando você adicionar uma categoria, você está adicionando métodos para a classe. O artigo da Wikipedia tem coisas boas .

A melhor maneira de olhar para esta diferença é que: 1. herança: quando quiser transformá-lo exatamente no seu caminho. exemplo: AsyncImageView para implementar o carregamento lento. Que é feito por herdar UIView. 2. categoria: Só quero adicionar um sabor extra para ele. exemplo: Queremos substituir todos os espaços do texto de um campo de texto

   @interface UITextField(setText)
      - (NSString *)replaceEscape;
   @end

   @implementation UITextField(setText)
      - (NSString *)replaceEscape
      {
         self.text=[self.text stringByTrimmingCharactersInSet:
                           [NSCharacterSet whitespaceCharacterSet]];
         return self.text;
      }
   @end

--- Ele irá adicionar uma nova propriedade ao campo de texto para você escapar todos os espaços em branco. Assim como adicionando uma nova dimensão a ele sem alterar completamente o seu caminho.

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