studio saber programar programacion porque para móviles libro importante edición desarrollo curso aplicaciones actualidad java c++ .net oop encapsulation

java - saber - Encapsulación: ¿por qué la necesitamos cuando los setters ya son públicos?



porque es importante saber programar en la actualidad (9)

Esta pregunta ya tiene una respuesta aquí:

La encapsulación está ocultando los datos. Me gustaría escuchar algunas respuestas realmente interesantes aquí.

¿Cuál es el punto detrás de mantener las variables como private cuando ya declaramos métodos de establecimiento public para variables?

Entiendo el uso de la encapsulación, pero cuando hacemos que los definidores sean públicos, ¿cuál es el punto detrás de mantener las variables como private Podemos usar directamente public modificadores de acceso public

¿Es porque no queremos que otros sepan la manera exacta en que almacenamos los datos o administramos los datos en el back-end?


¿Es porque no queremos que otros sepan la manera exacta en que almacenamos los datos o administramos los datos en el back-end?

Sí, ese es el punto. Está relacionado con los conceptos de abstracción y ocultación de la información .

Usted proporciona un configurador público que cuando es invocado por el cliente de la clase tendrá el efecto que usted ha documentado. No es asunto del cliente cómo se logra realmente este efecto. ¿Estás modificando uno de los atributos de la clase? Bien, déjale saber al cliente, pero no el hecho de que en realidad estás modificando una variable. En el futuro, es posible que desee modificar su clase para que, en lugar de una simple variable de copia de seguridad, utilice algo completamente diferente (¿un diccionario de atributos? ¿Un servicio externo? ¡Lo que sea!) Y el cliente no se rompa.

Entonces su configurador es una abstracción que le proporciona al cliente para "modificar este atributo de clase". Al mismo tiempo, está ocultando el hecho de que está utilizando una variable interna porque el cliente no necesita saberlo.

(Nota: aquí estoy usando la palabra "atributo" como un concepto genérico, no relacionado con ningún lenguaje de programación concreto)


¿Qué pasa si desea una verificación de rango antes de la asignación? Ese es uno de los casos que utilizo setters y getters.


El ejemplo más o menos simple y realista que encontré en la práctica es una clase de Options , que tiene muchos de los que establecen y obtienen. En algún momento, es posible que desee agregar una nueva opción que depende de otros o tiene efectos secundarios. O incluso reemplazar grupo de opciones con Enum . En este caso, la función setA no solo modificará a campo, sino que ocultará alguna lógica de configuración adicional. De getA similar, getA no solo devolverá el valor de a , sino algo así como config == cStuffSupportingA .


Establecer campos como documentos privados es un hecho poderoso: estos campos privados solo se usan directamente dentro de la clase actual. Esto ayuda a los mantenedores al no tener que rastrear el uso del campo. Pueden razonar mejor en el código mirando a la clase y determinando que los efectos en y desde estos campos con el entorno de la clase pasan por llamadas de métodos públicos y protegidos. Limita la superficie de exposición en la clase.

A su vez, definir un "setter" para un campo privado no se trata de darle publicidad nuevamente. Se trata de declarar otro hecho poderoso: un objeto que pertenece a esta clase tiene una propiedad que se puede modificar desde el exterior. (Los términos objeto y propiedad se utilizan en el sentido de una parte limitada del todo y un hecho observable sobre esta parte , no en el sentido de la POO).

¿Por qué, entonces, declarar un "setter" en un campo cuando hacer el campo público sería suficiente? Debido a que declarar un campo no solo se enlaza un nombre a una propiedad de los objetos de la clase, sino que también se compromete a usar el almacenamiento de memoria para esta propiedad.

Por lo tanto, si declara un "campo privado con un configurador", declara tres cosas:

  • Usted declara que el nombre que le dio al grupo de agrupador de campo / configurador representa una propiedad del objeto que es de interés cuando el objeto se ve como una caja negra.
  • Usted declara que el valor del objeto es modificable por el entorno.
  • Usted declara que en esta clase concreta en particular, la propiedad del objeto se realiza mediante la asignación de algo de almacenamiento de memoria.

Yo abogo por que nunca haga sus campos privados con captadores y definidores de manera indiscriminada. Los campos son para describir el almacenamiento. Los métodos son para las interacciones con el medio ambiente. (Y el caso particular de "getters" y "setters" son para describir propiedades de interés)


Estoy totalmente de acuerdo con , pero me gustaría añadir una cosa:

Hay casos en los que realmente no quieres esa abstracción . Y eso está bien.

Un ejemplo simple que me gusta usar aquí es una clase para un vector flotante tridimensional:

class Vector3f { public: float x; float y; float z; };

¿Podría hacer que esos campos sean privados y proporcionar establecedores en su lugar? Claro que podrías. Pero aquí podría argumentar que la clase realmente debe proporcionar una tupla de flotadores y no desea ninguna funcionalidad adicional. Por lo tanto, agregar establecedores solo complicaría la clase y preferiría dejar los campos públicos.

Ahora, puedes construir fácilmente escenarios en los que eso te pueda morder más adelante. Por ejemplo, es posible que un día obtenga el requisito de que Vector3f s no Vector3f permitido almacenar NaN s y debería lanzar una excepción si alguien intenta hacerlo. Pero este hipotético problema futuro no debería ser suficiente para justificar la introducción de abstracciones adicionales.

Es su decisión como programador decidir qué abstracciones tienen sentido para el problema en cuestión y cuáles solo se interpondrán en su manera de hacer el trabajo. Las abstracciones innecesarias son over-engineering y dañarán su productividad tanto como no abstraerlas lo suficiente.

En pocas palabras: no utilice a los colocadores a ciegas en todas partes solo porque alguien afirmó que es una buena práctica. En su lugar, piense en el problema en cuestión y considere las compensaciones.


Piensa en esto: estoy representando un objeto de la vida real, un León a través de una clase. Haría algo como esto.

class Lion { public int legs; }

Ahora, otro desarrollador necesita mi clase para crear un objeto y establecer su campo de patas. Haría algo como esto

Lion jungleKing = new Lion(); jungleKing.legs=15;

Ahora la pregunta es, Java no lo restringirá a establecer ningún número más de 4 como el número de patas para ese objeto. No es un error, y funcionará bien. Pero es un error lógico, y el compilador no te ayudará allí. De esta manera, un León puede tener cualquier cantidad de piernas. Pero si escribimos el código de esta manera.

class Lion { private int legs; public void setLegs(int legs){ if(legs>4) this.legs=4; else this.legs=legs; } }

Ahora no tendrá ningún León con más de 4 patas porque la política de actualización de los campos de la clase ha sido definida por la propia clase y no hay forma de que nadie sepa que la política actualizará el campo de patas porque la única manera para actualizar el campo de las piernas es a través del método setLegs () y ese método conoce la política de la clase.


Porque por encapsulación proporcionamos un único punto de acceso. Supongamos que define una variable y su definidor de la siguiente manera

String username; public void setUsername(String username){ this.username = username; }

Más tarde, le gustaría agregar alguna validación antes de configurar la propiedad de nombre de usuario Si está configurando el nombre de usuario en 10 lugares al acceder directamente a la propiedad, entonces no tiene un solo punto de acceso y necesita hacer este cambio en 10 lugares. Pero si tiene un método de establecimiento, al hacer un cambio en un lugar puede lograr fácilmente el resultado.


Si la answer es , me gustaría agregar que, en el caso particular de los establecedores públicos en lugar de exponer directamente los campos públicos que está preguntando, hay otra distinción muy importante que debe tener en cuenta aparte de la implementación de ocultación y desacoplamiento de información. de la superficie pública, o API , de una clase; validación

En un escenario de campo público, no hay forma de validar el valor del campo cuando se modifica. En el caso de un setter público (ya sea una propiedad de Foo {get; set;} o un SetFoo(Foo value) ), tiene la posibilidad de agregar un código de validación y lanzar los efectos secundarios necesarios y así garantizar que su clase sea siempre En un estado válido o previsible.


Wikipedia tiene una buena descripción de [métodos mutadores ( https://en.wikipedia.org/wiki/Mutator_method ), que es lo que son los métodos de establecimiento y cómo funcionan en diferentes idiomas.

La versión corta: si desea introducir validación u otra lógica que se ejecute en la modificación de objetos, es bueno tener un configurador para poner esa lógica. También puede ocultar cómo almacena las cosas. Por lo tanto, esas son razones para tener getters / setters. De manera similar, para quienes los obtienen, es posible que tenga una lógica que proporcione valores predeterminados o que dependan de, por ejemplo, la configuración de cosas como la configuración regional, la codificación de caracteres, etc. Hay muchas razones válidas para querer tener otra lógica que no sea obtener o configurar la variable de instancia .

Obviamente, si tiene captadores y definidores, no querrá que las personas los eviten mediante la manipulación directa del estado del objeto, por lo que debe mantener la privacidad de las variables de instancia.

Otras cosas a considerar incluyen si realmente quiere que sus objetos sean mutables (de lo contrario, haga que los campos sean finales), si desea que la modificación del estado del objeto sea segura para el bloqueo de los objetos, por ejemplo, bloqueos, sincronizados, etc.