objective-c immutability

La mejor manera de definir una clase inmutable en Objective C



objective-c immutability (2)

Soy un novato en Objective C y me preguntaba cuál es la mejor manera de definir una clase inmutable en Objective-C (como NSString, por ejemplo).

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

Pienso que :

  • no se deben proporcionar setters
  • Si se usan propiedades, deben ser leídas solo
  • para "deshabilitar" la codificación del valor clave, accessInstanceVariablesDirectly debe ser anulada y devolver NO

¿Olvidé algo?

Gracias


Creo que de la manera que lograría esto es que el archivo de encabezado contenga solo la información que se necesita públicamente. El resto iría al archivo de origen para limitar la posible exposición de anulación.

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

Hace mucho tiempo llegué a la conclusión de que realmente no se puede usar Objective-C como usaría Java, C ++ o C #. Objective-C es simplemente demasiado diferente. De hecho, creo que existen diferencias drásticas de paradigma, como el envío / las llamadas de método estático frente al dinámico.

La razón por la que menciono esto es porque tal vez ninguna clase en Objective-C es realmente definitiva. Quizás esto sea por diseño de lenguaje y no por algo que debas intentar solucionar. Si lo haces, finalmente complicarás innecesariamente tu código.


Lo primero y más importante que debe hacer es incluir comentarios de uso en su archivo .h que expliquen que esta es una clase inmutable, junto con el propósito de la clase y la guía de uso general. Con demasiada frecuencia, la gente hace todo lo posible para tratar de "imponer" con el compilador lo que podría lograrse simplemente informando a la persona que llama.

Ciertamente, no debe proporcionar establecedores públicos ni propiedades de readwrite si pretende que la clase sea inmutable (pero, por supuesto, debe proporcionar definidores privados para que pueda usar los accesores dentro de la clase; siempre debe evitar, incluso internamente, jugar con los ivars directamente, excepto en algunos lugares). Supongo que usted podría agregar su invalidación accessInstanceVariablesDirectly si vio esto como un posible error por parte de la persona que llama.

Pero la clave para comprender Objective-C es comprender y aceptar el hecho de que la persona que llama no es el enemigo. El código llamado no necesita estar "protegido" de la persona que llama. La persona que llama necesita estar protegida de un error probable. Todos estamos en el mismo lado aquí; llamador y llamado quiere que el programa funcione.

La persona que llama es el cliente y debe ser tratada como tal. El cliente no siempre tiene la razón, pero el cliente es siempre 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 instaladores públicos a una clase inmutable es casi engañar a la persona que llama a cometer 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 imponer la inmutabilidad. La persona que llama puede casi (*) violar la encapsulación accediendo directamente a la estructura ( object->ivar ). La persona que llama sería una tontería si lo hiciera, pero sería aún más necio tratar de evitarlo. Tenga en cuenta la inmutabilidad, oculte sus setters y marque sus propiedades solo, y en casi todos los casos debería estar bien.

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