2010-04-05 605 views
17

Soy un novato en Objective C y me preguntaba qué es la mejor manera de definir una clase inmutable en Objective-C (como NSString, por ejemplo).La mejor manera de definir una clase inmutable en Objectivo C

Quiero saber cuáles son las reglas básicas que uno tiene que seguir para que una clase sea inmutable.

creo que:

    no deben ser proporcionados
  • set
  • si se utilizan las propiedades, que debe ser de sólo lectura
  • a "desactivar" Valor Codificación Key, accessInstanceVariablesDirectly debe haber anulación y volver NO

¿Olvidé algo?

Gracias

Respuesta

13

Lo primero y más importante que debe hacer es incluir comentarios de uso en su archivo .h que explique que esta es una clase inmutable, junto con el propósito de la clase y la guía de uso general. Con demasiada frecuencia las personas hacen todo lo posible para tratar de "hacer cumplir" con el compilador lo que se puede lograr simplemente informando a la persona que llama.

Por cierto, no debe proporcionar los emisores públicos o propiedades ReadWrite si tiene la intención de la clase que son inmutables (pero por supuesto que debe proporcionar los emisores privados para que pueda utilizar descriptores de acceso dentro de la clase, siempre se debe evitar, incluso internamente , jugando con ivars directamente excepto en algunos lugares). Supongo que puede agregar su anulación accessInstanceVariablesDirectly si ve esto como un probable error por parte de la persona que llama.

Pero la clave para entender Objective-C es comprender y aceptar el hecho de que quien llama no es el enemigo. El código llamado no necesita estar "protegido" de la persona que llama. La persona que llama debe estar protegida de posibles errores. Todos están del mismo lado aquí; llamante y llamado quieren que el programa funcione.

La persona que llama es cliente y debe tratarse como tal. El cliente no siempre tiene la razón, pero el cliente siempre es el cliente. A veces eso significa proteger al cliente de sí mismo si hay un error fácil que pueda cometer. NSAssert() es particularmente útil para eso. Y proporcionar a los organismos públicos a una clase inmutable casi engaña a la persona que llama para que cometa un error, por lo que sería malo para todos.

En cualquier caso, no debe hacer que su clase sea demasiado compleja para tratar de forzar la inmutabilidad. La persona que llama casi puede (*) violar la encapsulación al acceder directamente a la estructura (object->ivar). La persona que llama sería tonto al hacerlo, pero sería aún más tonto tratar de evitarlo. Tenga en cuenta la inmutabilidad, oculte sus incubadores y marque sus propiedades de solo lectura, y en casi todos los casos debería estar bien.

(*) Sí, es posible ocultar aún más sus datos al anidar una estructura/objeto privado como un ivar, pero la persona que llama puede modificar los datos con la aritmética del puntero para que no se "aplique". Siempre pregúntate qué problema realmente estás tratando de resolver.

+0

La misma lógica se aplica a los singletons 'defensivos', supongo? –

+2

Absolutamente. Los singletons forzados (overriding + allocWithZone :) son casi siempre un error y hacen más daño que bien. El único lugar que tendría sentido es si * desea * que la naturaleza singleton sea un detalle de implementación privada. De lo contrario, normalmente debería utilizar el patrón "singleton compartido" donde se permiten múltiples instancias, o bien debería hacer que la creación de una segunda instancia sea un error de programación con NSAssert(). –

+1

+1 para la postura de "todos están en el mismo bando". –

6

yo creo que como había lograr esto es hacer que el archivo de cabecera contiene sólo la información necesaria públicamente. El resto iría al archivo fuente para limitar la posible anulación de la exposición.

Dado que Objective-C aparentemente no tiene una forma definitiva de definir una clase como final (sellada, etc.), todo lo que podrías hacer no es todo lo que abarca.

Hace mucho tiempo llegué a la conclusión de que realmente no puedes usar Objective-C como si usaras Java, C++ o C#. Objective-C es simplemente demasiado diferente. De hecho, creo que hay diferencias de paradigma drásticas, como el envío/llamadas de métodos estáticos frente a dinámicos.

La razón por la que menciono esto es porque tal vez ninguna clase en Objective-C es verdaderamente definitiva. Tal vez esto se deba al diseño del lenguaje y no es algo que deba tratar de evitar. Si lo haces, finalmente complicarías innecesariamente tu código.

Cuestiones relacionadas