Pregunta

En Ruby, hay Módulos y se puede extender una clase por "mezclar" el módulo.

module MyModule
  def printone
    print "one" 
  end
end

class MyClass
  include MyModule
end

theOne = MyClass.new
theOne.printone 
>> one

En Objective-C, me parece que tiene un conjunto de métodos comunes que quiero un número de la Clase a "heredar".¿Qué otras maneras puedo lograr esto sin la creación de una clase común y derivar todo desde que el común de la clase?

¿Fue útil?

Solución

Editar:los cambios añadidos debido a que algunas personas me siento responsable de las limitaciones de Objective-C.

Respuesta corta:usted no puede.Objective-C no tiene el equivalente de Ruby mixins.

Un poco menos de respuesta corta:Objective-C tiene algo con posiblemente el mismo sabor:los protocolos.Protocolos (Interfaces en otros lenguajes), son una manera de definir un conjunto de métodos de una clase que adopta los protocolos se compromete a implementar.Un protocolo no proporciona una implementación.Esta limitación impide el uso de protocolos como un equivalente exacto en Ruby mixins.

Menos aún respuesta corta: Sin embargo, el Objetivo-C de tiempo de ejecución de estar expuesta una API que te permite jugar con las características dinámicas de la lengua.Entonces que paso fuera de la lengua, pero usted puede tener protocolos con implementaciones predeterminadas (también llamado hormigón protocolos).Vladimir respuesta muestra una manera de hacer eso.En ese punto me parece que usted consigue Ruby mixins bien.

Sin embargo, no estoy seguro de que yo recomendaría hacer eso.En la mayoría de los casos, los otros modelos se ajustan a la ley sin jugar a los juegos con el tiempo de ejecución.Por ejemplo, usted puede tener un sub-objeto que implemente el mixto en el método (tiene-una en lugar de es-un).Jugando con el tiempo de ejecución está bien, pero tiene 2 inconvenientes:

  • Usted hace su código menos legible, ya que requiere que los lectores sepan mucho más que el idioma.Asegúrese de que usted puede (y debe) comentario, pero recuerda que cualquier comentario puede ser visto como un defecto de la aplicación.

  • Usted depende de que la implementación de la lengua.Seguro, las plataformas de Apple son, con mucho, los más comunes para Objective-C, pero no olvides Cocotron o GnuStep (o Etoilé) que tienen diferentes tiempos de ejecución, que puede o no puede ser compatible con Apple en ese aspecto.

Como una nota del lado, he estado por debajo de que las categorías no pueden agregar estado (variables de instancia) a una clase.Mediante el uso de la API del motor de ejecución, usted puede levantar esa limitación también.Esto está más allá del alcance de esta respuesta, sin embargo.

Respuesta larga:

Dos Objective-C características como posibles candidatos:categorías y protocolos.Las categorías no son realmente el derecho de elección aquí, si entiendo la pregunta correctamente.La característica es un protocolo.

Permítanme darles un ejemplo.Supongamos que quiero un montón de clases y tienen una habilidad que se llama "cantar".A continuación, se define un protocolo:

@protocol Singer
    - (void) sing;
@end

Ahora puede declarar que ninguna de sus propias clases adopta el protocolo de la siguiente manera:

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

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

Declarando que ellos adopten el protocolo se comprometen a la implementación de la sing método.Por ejemplo:

@implementation Rectangle

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

@end

@implementation Car

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

@end

A continuación, utilice las clases, por ejemplo como este:

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

Observe que los cantantes en la matriz no es necesario tener una superclase común.Observe también que una clase sólo puede tener una superclase, pero muchos adoptado protocolos.Aviso, finalmente, que la comprobación de tipos se realiza por el compilador.

En efecto, el protocolo es el mecanismo de la herencia múltiple se utiliza para el mixin patrón.Que la herencia múltiple es severamente limitada debido a un protocolo no puede añadir nuevas variables de instancia de una clase.Un protocolo solamente describe la interfaz pública de los adoptantes deben implementar.A diferencia de Ruby módulos no contiene una implementación.

Que la mayor parte de ella.Vamos a mencionar las categorías.

Una categoría es declarado no en corchetes angulares, pero entre paréntesis.La diferencia es que una categoría puede ser definido por una clase existente para expandirla, sin que la subclasificación.Incluso puede hacerlo para un sistema de clase.Como se puede imaginar, es posible utilizar las categorías para implementar algo similar a mixin.Y ellos fueron utilizados de esa manera por un largo tiempo por lo general como categoría a NSObject (el típico de la raíz de la jerarquía de herencia), a tal punto que ellos fueron llamados "informales" de los protocolos.

Es informal porque 1 - ningún tipo de comprobación es realizada por el compilador, y 2 - la aplicación de los métodos de protocolo es opcional.

No es necesario hoy en día el uso de categorías como protocolos, especialmente debido a que los protocolos formales ahora puede declarar que algunos de sus métodos son opcionales con la palabra clave @optional o requerido (el valor predeterminado) con @required.

Las categorías son todavía útiles para añadir algo de dominio específico de la conducta para una clase existente. NSString es un objetivo común para que.

También es interesante señalar que la mayoría (si no todos) de NSObject las instalaciones son, de hecho, declaró en una NSObject protocolo.Esto significa que no es realmente convincente para el uso de NSObject como una superclase de todas las clases, a pesar de que comúnmente se hace por razones históricas, y bueno...porque no hay ningún inconveniente para hacerlo.Pero algunas de las clases del sistema, tales como NSProxy, son no NSObject.

Otros consejos

Enchufe desvergonzado: ObjectiveMixin

Se aprovecha de la capacidad de Objective-C de tiempo de ejecución de la adición de métodos para una clase en tiempo de ejecución (en oposición a categorías, que son solamente en tiempo de compilación). Comprobar que funciona, funciona bastante bien y de una manera similar a mixins de Ruby.

Puede literalmente mixin utilizando el código # include. Esto no es aconsejable y está en contra de todas las religiones en Objective-C, sin embargo, funciona perfectamente.

Por favor, no lo haga en el código de producción.

por ejemplo, en el archivo:

MixinModule.header (no debe ser compilado o copiado en el objetivo)

-(void)hello;

MixinModule.body (no debe ser compilado o copiado en el objetivo)

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

en la clase 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, no lo haga en el código de producción.

Esta es mi opinión sobre la implementación de Mixins en Objective-C, sin necesidad de utilizar directamente el tiempo de ejecución de Objective-C. Tal vez sea útil a alguien: https://stackoverflow.com/a/19661059/171933

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