Pregunta

Puede alguien explicarme la diferencia entre las categorías y la herencia en Objective C? He leído la entrada en Wikipedia y la discusión sobre las categorías que no lo hace ninguna diferencia respecto a la de la herencia. También busqué en la discusión sobre el tema en el libro "Open iPhone Desarrollo" y todavía no lo entiendo.

¿Fue útil?

Solución

A veces, la herencia sólo parece más problemas de lo que vale. Se utiliza correctamente cuando se quiere añadir algo a una clase existente de que se produzca un cambio en el comportamiento de esa clase.

Con una categoría, lo que desea el objeto existente para hacer un poco más. Como ya se ha dado, si lo que desea es tener una clase de cadena que se encarga de la compresión, no es necesario crear subclases de la clase string, que acaba de crear una categoría que se encarga de la compresión. De esta manera, no es necesario cambiar el tipo de las clases de cuerda que ya utiliza.

La clave está en la restricción de que las categorías sólo se suman los métodos, no se puede añadir variables a una clase utilizando categorías. Si la clase necesita más propiedades, entonces tiene que ser una subclase.. (Edit: se puede utilizar el almacenamiento asociativo, creo)

Las categorías son una buena manera de añadir funcionalidad al mismo tiempo conforme a un principio orientado a objetos a preferir composición sobre la herencia.

Editar de enero de 2012

Las cosas han cambiado ahora. Con el compilador LLVM actual, y la moderna, el tiempo de ejecución de 64 bits, puede agregar Ivars y propiedades de la clase extensiones (no categorías). Esto le permite mantener Ivars privados fuera de la interfaz pública. Pero, si se declara propiedades de los Ivars, aún pueden ser accedidos / cambiado a través de KVC, porque todavía no hay tal cosa como un método privado en Objective-C.

Otros consejos

Categorías le permiten añadir métodos a las clases existentes. Así que en lugar de subclase NSData para añadir sus nuevos métodos de cifrado cobardes, se puede añadir directamente a la clase NSData. Cada objeto NSData en su aplicación tiene acceso a esos métodos.

Para ver lo útil que puede ser, mira: CocoaDev

Uno de los ejemplos favoritos de categorías Objective-C en la acción es NSString. NSString se define en el marco de la Fundación, que no tiene noción de vistas o ventanas. Sin embargo, si se utiliza un NSString en una aplicación Cocoa se dará cuenta de que responde a mensajes como – drawInRect:withAttributes:.

AppKit define una categoría para NSString que proporciona métodos de dibujo adicionales. La categoría permite a los nuevos métodos que se añaden a una clase existente, por lo que estamos todavía sólo se ocupan de NSStrings. Si AppKit vez implementado dibujo de subclases que tendríamos que hacer frente a 'AppKitStrings' o 'NSSDrawableStrings' o algo así.

Categorías le permiten agregar la aplicación o dominio métodos específicos a las clases existentes. Puede ser muy potente y muy práctica.

Si como programador se le da un conjunto completo de código fuente para una biblioteca de código o aplicación, se puede volver loco y cambiar lo que sea necesario para lograr su objetivo de programación con ese código.

Por desgracia, esto no siempre es el caso, ni siquiera deseable. Muchas veces se le da una biblioteca kit binaria / objeto y un conjunto de cabeceras que conformarse con.

A continuación, se necesita una nueva funcionalidad para una clase por lo que podría hacer un par de cosas:

  1. crear una nueva clase entera en lugar de una clase stock -. Replegar todas sus funciones y miembros vuelva a grabar todo el código para utilizar la nueva clase

  2. crear una nueva clase de contenedor que contiene la clase de valores como un miembro (composición) y volver a escribir el código base para utilizar la nueva clase.

  3. parches binarios de la biblioteca para cambiar el código (buena suerte)

  4. obligar al compilador para ver a su nueva clase que el anterior, y espero que no depende de un cierto tamaño o el lugar de los puntos de memoria y de entrada específica.

  5. especialización subclase - crear subclases para añadir funcionalidad y modificar código del controlador para utilizar la subclase lugar - en teoría no debería haber algunos problemas y si es necesario agregar miembros de datos que sea necesario, pero la huella de la memoria será diferente. Usted tiene la ventaja de tener tanto el nuevo código y el código antiguo disponible en la subclase y elegir cuál utilizar, el método de la clase base o el método reemplazado.

  6. modificar la clase objc necesario, con una definición de categoría que contiene métodos para hacer lo que quiere y / o anular los viejos métodos de las clases de acciones.

    Esto también puede corregir errores en la biblioteca o personalizar los métodos para nuevos dispositivos de hardware o lo que sea. No es una panacea, pero permite la adición de método de clase sin tener que recompilar la clase / biblioteca que no se ha modificado. La clase original es el mismo en el código, tamaño de la memoria, y los puntos de entrada, por lo que las aplicaciones heredadas no se rompen. El compilador simplemente pone el nuevo método (s) en el tiempo de ejecución como perteneciente a esa clase, y anula métodos con la misma firma como en el código original.

    un ejemplo:

    Tiene un Bing clase que da salida a un terminal, pero no a un puerto serie, y ahora que es lo que necesita. (por alguna razón). Tiene Bing.h y libBing.so, pero no Bing.m en su kit.

    La clase Bing hace todo tipo de cosas internamente, ni siquiera saber todo lo que, sólo tiene la API pública en la cabecera.

    Usted es inteligente, por lo que se crea una categoría (SERIALOUTPUT) para la clase 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
    

    El compilador obliga a crear un objeto que puede estar vinculado con su aplicación y el tiempo de ejecución ahora sabe que Bing responde a @selector (ToSerial :) y se puede utilizar como si la clase Bing fue construido con ese método. No se puede agregar miembros de datos únicos métodos y esto no tenía la intención de crear tumores gigantes de código unidas a las clases de base, pero tiene sus ventajas sobre los idiomas estrictamente mecanografiadas.

Creo que algunas de estas respuestas, al menos, apuntan a la idea de que la herencia es una forma más pesada de agregar funcionalidad a una clase existente, mientras que las categorías son más ligeros.

La herencia se utiliza cuando se está creando una nueva jerarquía de clases (todas las campanas y silbatos) y podría decirse que aporta una gran cantidad de trabajo cuando elegido como el método de añadir funcionalidad a las clases existentes.

Como alguien aquí lo puso ... Si está utilizando la herencia para añadir un nuevo método, por ejemplo, a NSString, usted tiene que ir y cambiar el tipo que está utilizando en cualquier otro código en el que desea utilizar esta nueva método. Sin embargo, si se utiliza categorías, sólo tiene que llamar al método de tipos NSString existente, sin subclases.

Los mismos objetivos se pueden lograr con cualquiera, pero categorías parecen darnos una opción que es más sencillo y requiere menos mantenimiento (probablemente).

Alguien sabe si hay situaciones en las categorías son absolutamente necesarias?

Una categoría es como un mixin: un módulo en Ruby, o algo así como una interfaz en Java. Se puede pensar en él como "métodos desnudos". Cuando se agrega una categoría, va a añadir métodos a la clase. El artículo de Wikipedia tiene cosas buenas .

La mejor manera de mirar a esta diferencia es que: 1. herencia: cuando quieren convertir exactamente en su camino. ejemplo: AsyncImageView para poner en práctica la carga diferida. Que se realiza heredando UIView. 2. Categoría: Sólo quiero agregar un sabor adicional a ella. ejemplo: Queremos reemplazar todos los espacios del texto de un 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

--- Se añade una nueva propiedad al campo de texto para que usted pueda escapar de todos los espacios en blanco. Al igual que añadir una nueva dimensión a la misma sin cambiar por completo su manera.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top