¿Por qué usar getters y setters / accessors?

1544

¿Cuál es la ventaja de usar getters y setters, que solo obtienen y establecen, en lugar de simplemente usar campos públicos para esas variables?

Si getters y setters están haciendo algo más que el simple get / set, puedo resolver esto muy rápido, pero no estoy 100% claro sobre cómo:

public String foo;

es peor que:

private String foo;
public void setFoo(String foo) { this.foo = foo; }
public String getFoo() { return foo; }

Mientras que el primero toma mucho menos código repetitivo.

Dean J
fuente
66
@Dean J: Duplica con muchas otras preguntas: stackoverflow.com/search?q=getters+setters
Asaph
8
Por supuesto, ambos son igualmente malos cuando el objeto no necesita una propiedad para ser cambiado. Prefiero hacer que todo sea privado, y luego agregar getters si es útil, y setters si es necesario.
Tordek
26
Google "los accesos son malvados"
OMG Ponies
34
"Los accesores son malvados" si está escribiendo código funcional u objetos inmutables. Si estás escribiendo objetos mutables con estado, entonces son bastante esenciales.
Christian Hayter
18
Dile, no preguntes. pragprog.com/articles/tell-dont-ask
Dave Jarvis

Respuestas:

982

En realidad, hay muchas buenas razones para considerar el uso de accesores en lugar de exponer directamente los campos de una clase, más allá del argumento de encapsulación y facilitar los cambios futuros.

Estas son algunas de las razones que conozco:

  • Encapsulación del comportamiento asociado con la obtención o configuración de la propiedad: esto permite agregar funcionalidades adicionales (como la validación) más fácilmente más adelante.
  • Ocultar la representación interna de la propiedad mientras expone una propiedad utilizando una representación alternativa.
  • Aislar su interfaz pública del cambio, permitiendo que la interfaz pública permanezca constante mientras la implementación cambia sin afectar a los consumidores existentes.
  • Controlar la semántica de la vida útil y la gestión de la memoria (eliminación) de la propiedad, particularmente importante en entornos de memoria no gestionados (como C ++ u Objective-C).
  • Proporcionar un punto de intercepción de depuración para cuando una propiedad cambia en tiempo de ejecución; depurar cuándo y dónde una propiedad cambia a un valor particular puede ser bastante difícil sin esto en algunos idiomas.
  • Interoperabilidad mejorada con bibliotecas que están diseñadas para operar contra captadores / establecedores de propiedades: burlas, serialización y WPF vienen a la mente.
  • Permitir que los herederos cambien la semántica de cómo se comporta y se expone la propiedad anulando los métodos getter / setter.
  • Permitir que el getter / setter se pase como expresiones lambda en lugar de valores.
  • Los getters y setters pueden permitir diferentes niveles de acceso; por ejemplo, get puede ser público, pero el conjunto podría estar protegido.
LBushkin
fuente
6060
+1. Solo para agregar: permite la carga diferida. Permitir copia en escritura.
NewbiZ
66
@bjarkef: creo que los publicmétodos de acceso causan duplicación de código y exponen información. Los accesos públicos no son necesarios para la clasificación (serialización). En algunos lenguajes (Java), los publicaccesos get no pueden cambiar el tipo de retorno sin romper las clases dependientes. Además, creo que van en contra de los principios de OO. Ver también: stackoverflow.com/a/1462424/59087
Dave Jarvis el
15
@sbi: Una cosa que se compra utilizando un establecedor de propiedades, incluso en un marco bien diseñado, es la capacidad de hacer que un objeto notifique a otro cuando una propiedad cambia.
supercat
22
@supercat: Sin embargo, en general, no estoy promoviendo datos públicos. La notificación de otros objetos también puede hacerse a partir de métodos reales que proporcionan una abstracción significativa en un simple contenedor de datos con (más o menos) campos de datos públicos. En lugar de plane.turnTo(dir); plane.setSpeed(spd); plane.setTargetAltitude(alt); plane.getBreaks().release();querer decir plane.takeOff(alt). Los campos de datos internos que deben cambiarse para poner el avión en el takingOffmodo no son de mi incumbencia. Y qué otros objetos ( breaks) notifica el método tampoco quiero saber.
sbi
8
@BenLee: Realmente no sé cómo decirlo. "Accessors" es solo un sinónimo de "getters / setters", y en mis dos primeros comentarios expliqué por qué esos son un abuso del término "OOP". Si necesita alcanzarlo y manipular el estado directamente, no es un objeto en el sentido OOP de ese término.
sbi
480

Debido a que dentro de 2 semanas (meses, años) a partir de ahora, cuando se dé cuenta de que su setter necesita hacer más que solo establecer el valor, también se dará cuenta de que la propiedad se ha utilizado directamente en otras 238 clases :-)

ChssPly76
fuente
84
Estoy sentado y mirando una aplicación de línea de 500k donde nunca se ha necesitado. Dicho esto, si se necesita una vez, comenzaría a causar una pesadilla de mantenimiento. Lo suficientemente bueno para una marca de verificación para mí.
Dean J
20
Solo puedo envidiarte a ti y a tu aplicación :-) Dicho esto, también depende de tu pila de software. Delphi, por ejemplo (y C #, ¿creo?) Le permite definir propiedades como ciudadanos de primera clase donde pueden leer / escribir un campo directamente al principio pero, si lo necesita, hacerlo también a través de métodos getter / setter. Mucho conveniente. Java, por desgracia, no lo hace, sin mencionar el estándar de JavaBeans que te obliga a usar getters / setters también.
ChssPly76
14
Si bien esta es una buena razón para usar accesores, muchos entornos de programación y editores ahora ofrecen soporte para la refactorización (ya sea en el IDE o como complementos gratuitos) que de alguna manera reduce el impacto del problema.
LBushkin
62
suena como optimización pre-madura
cmcginty
41
La pregunta que debe hacerse cuando se pregunta si implementar getters y setters es: ¿por qué los usuarios de una clase tendrían que acceder a las entrañas de la clase? Realmente no importa si lo hacen directamente o protegidos por una pseudo capa delgada: si los usuarios necesitan acceder a los detalles de la implementación, eso es una señal de que la clase no ofrece suficiente abstracción. Ver también este comentario .
sbi
358

Un campo público no es peor que un par getter / setter que no hace nada más que devolver el campo y asignarlo. Primero, está claro que (en la mayoría de los idiomas) no hay diferencia funcional. Cualquier diferencia debe estar en otros factores, como la capacidad de mantenimiento o la legibilidad.

Una ventaja a menudo mencionada de los pares getter / setter, no lo es. Existe la afirmación de que puede cambiar la implementación y sus clientes no tienen que ser recompilados. Supuestamente, los configuradores le permiten agregar funcionalidades como validación más adelante y sus clientes ni siquiera necesitan saberlo. Sin embargo, agregar validación a un colocador es un cambio en sus condiciones previas, una violación del contrato anterior , que era, simplemente, "puede poner cualquier cosa aquí, y puede obtener lo mismo más tarde del getter".

Entonces, ahora que rompió el contrato, cambiar todos los archivos en la base de código es algo que debe hacer, no evitar. Si lo evita, está asumiendo que todo el código asumió que el contrato para esos métodos era diferente.

Si ese no hubiera sido el contrato, entonces la interfaz estaba permitiendo a los clientes poner el objeto en estados no válidos. Eso es exactamente lo opuesto a la encapsulación. Si ese campo no se pudo establecer realmente desde el principio, ¿por qué no se realizó la validación desde el principio?

Este mismo argumento se aplica a otras supuestas ventajas de estos pares getter / setter de transferencia: si luego decide cambiar el valor establecido, está rompiendo el contrato. Si anula la funcionalidad predeterminada en una clase derivada, de una manera más allá de algunas modificaciones inofensivas (como el registro u otro comportamiento no observable), está rompiendo el contrato de la clase base. Esa es una violación del Principio de sustituibilidad de Liskov, que se considera uno de los principios de OO.

Si una clase tiene estos captadores y establecedores tontos para cada campo, entonces es una clase que no tiene invariantes, ni contrato . ¿Es realmente un diseño orientado a objetos? Si toda la clase tiene esos captadores y establecedores, es solo un titular de datos tonto, y los titulares de datos tontos deberían verse como titulares de datos tontos:

class Foo {
public:
    int DaysLeft;
    int ContestantNumber;
};

Agregar pares getter / setter de paso a dicha clase no agrega valor. Otras clases deberían proporcionar operaciones significativas, no solo operaciones que los campos ya proporcionan. Así es como puedes definir y mantener invariantes útiles.

Cliente : "¿Qué puedo hacer con un objeto de esta clase?"
Diseñador : "Puedes leer y escribir varias variables".
Cliente : "Oh ... genial, supongo?"

Hay razones para usar getters y setters, pero si esas razones no existen, hacer pares getter / setter en nombre de dioses de encapsulación falsa no es algo bueno. Las razones válidas para hacer captadores o establecedores incluyen las cosas que a menudo se mencionan como los posibles cambios que puede realizar más adelante, como la validación o diferentes representaciones internas. O tal vez el valor debería ser legible por los clientes pero no escribible (por ejemplo, leer el tamaño de un diccionario), por lo que un simple captador es una buena opción. Pero esas razones deberían estar ahí cuando elijas, y no solo como algo potencial que podrías desear más adelante. Esta es una instancia de YAGNI ( No lo vas a necesitar ).

R. Martinho Fernandes
fuente
13
Gran respuesta (+1). Mi única crítica es que me tomó varias lecturas descubrir cómo la "validación" en el párrafo final difería de la "validación" en los primeros (que descartó en el último caso pero promovió en el primero); ajustar la redacción podría ayudar en ese sentido.
ligereza corre en órbita el
14
Esta es una gran respuesta, pero lamentablemente la era actual ha olvidado qué es "ocultar información" o para qué sirve. Nunca leyeron sobre la inmutabilidad y en su búsqueda de los más ágiles, nunca dibujaron ese diagrama de transición de estado que definía cuáles eran los estados legales de un objeto y, por lo tanto, cuáles no.
Darrell Teague el
2
Una observación clave es que los getters son mucho más útiles que los setters. Un captador puede devolver un valor calculado o un valor calculado en caché. Todo lo que puede hacer un setter es alguna validación y luego cambiar el privatecampo. Si una clase no tiene setters, es fácil hacerla inmutable.
Raedwald
77
Er, supongo que no sabes lo que es una clase invariante. Si es una estructura no trivial, significa que tiene invariantes que mantener y uno simplemente no puede diseñarla sin tenerlo en cuenta. "Hubo un error, un miembro se actualizó incorrectamente". también se lee más o menos como "Una actualización de miembro violó a los invariantes de clase". Una clase bien diseñada no permite que el código del cliente viole sus invariantes.
R. Martinho Fernandes
55
+1 para 'los titulares de datos tontos deberían verse como titulares de datos tontos' Desafortunadamente, todo el mundo parece diseñar todo alrededor de los titulares de datos tontos en estos días, y muchos marcos incluso lo requieren ...
Joeri Hendrickx
93

Mucha gente habla de las ventajas de los captadores y setters, pero quiero jugar al abogado del diablo. En este momento estoy depurando un programa muy grande en el que los programadores decidieron hacer que todo sea getters y setters. Eso puede parecer agradable, pero es una pesadilla de ingeniería inversa.

Digamos que estás mirando a través de cientos de líneas de código y te encuentras con esto:

person.name = "Joe";

Es un código maravillosamente simple hasta que te das cuenta de que es un setter. Ahora, sigue a ese configurador y descubre que también establece person.firstName, person.lastName, person.isHuman, person.hasReallyCommonFirstName y llama a person.update (), que envía una consulta a la base de datos, etc. Oh, eso es donde estaba ocurriendo su pérdida de memoria.

La comprensión de un código local a primera vista es una propiedad importante de buena legibilidad que los captadores y establecedores tienden a romper. Es por eso que trato de evitarlos cuando puedo y minimizar lo que hacen cuando los uso.

Kai
fuente
8
Si. Actualmente refactorizando una gran base de código, y esto ha sido una pesadilla. Los captadores y establecedores hacen demasiado, incluyendo llamar a otros captadores y colocadores muy ocupados que terminan reduciendo la legibilidad a nada. La validación es una gran razón para usar los accesorios, pero usarlos para hacer mucho más de lo que parece eliminar cualquier beneficio potencial.
Fadecomic
31
Este es un argumento contra el azúcar sintáctico, no contra los setters en general.
Phil
66
Verdadero y verdadero, pero además, señala cómo los establecedores de propiedades individuales abren la puerta a estados inválidos sin ningún remedio para garantizar la integridad de cualquier objeto dado que permita que se filtre la abstracción.
Darrell Teague el
"Es un código maravillosamente simple hasta que te das cuenta de que es un setter" - oye, ¿fue la publicación original sobre Java o sobre C #? :)
Honza Zidek
Estoy completamente de acuerdo con respecto a la legibilidad. Es totalmente explícito lo que sucede cuando person.name = "Joe";se llama. La información no se cruza, el resaltado de sintaxis muestra que es un campo y la refactorización es más simple (no es necesario refactorizar dos métodos y un campo). En segundo lugar, todos esos ciclos cerebrales desperdiciados que piensan "getIsValid ()" o deberían ser "isValid ()", etc., pueden olvidarse. No puedo pensar en una sola vez que un getter / setter me haya salvado de un error.
Will
53

Hay muchas razones. Mi favorito es cuando necesitas cambiar el comportamiento o regular lo que puedes establecer en una variable. Por ejemplo, supongamos que tenía un método setSpeed ​​(int speed). Pero desea que solo pueda establecer una velocidad máxima de 100. Haría algo como:

public void setSpeed(int speed) {
  if ( speed > 100 ) {
    this.speed = 100;
  } else {
    this.speed = speed;
  }
}

Ahora, ¿qué pasa si EN CUALQUIER LUGAR de su código estaba usando el campo público y luego se dio cuenta de que necesita el requisito anterior? Diviértete buscando cada uso del campo público en lugar de solo modificar tu setter.

Mis 2 centavos :)

Peter D
fuente
62
Buscar cada uso del campo público no debería ser tan difícil. Hazlo privado y deja que el compilador los encuentre.
Nathan Fellman
12
eso es cierto, por supuesto, pero ¿por qué hacerlo más difícil de lo que fue diseñado? El enfoque get / set sigue siendo la mejor respuesta.
Hardryv
28
@Nathan: Encontrar otros usos no es el problema. Cambiarlos a todos es.
Graeme Perrow el
22
@GraemePerrow tener que cambiarlos todos es una ventaja, no un problema :( ¿Qué pasaría si tuvieras un código que supusiera que la velocidad podría ser superior a 100 (porque, ya sabes, antes de romper el contrato, podría!) ( while(speed < 200) { do_something(); accelerate(); })
R. Martinho Fernandes
29
¡Es un MUY mal ejemplo! Alguien debería llamar: myCar.setSpeed(157);y después de algunas líneas speed = myCar.getSpeed();Y ahora ... Les deseo una feliz depuración mientras trato de entender por qué speed==100cuándo debería ser157
Piotr Aleksander Chmielowski
53

En un mundo puramente orientado a objetos, los captadores y establecedores son un antipatrón terrible . Lea este artículo: Getters / Setters. Mal. Periodo . En pocas palabras, alientan a los programadores a pensar en los objetos como estructuras de datos, y este tipo de pensamiento es puramente de procedimiento (como en COBOL o C). En un lenguaje orientado a objetos no hay estructuras de datos, sino solo objetos que exponen el comportamiento (¡no atributos / propiedades!)

Puede encontrar más información sobre ellos en la Sección 3.5 de Objetos elegantes (mi libro sobre programación orientada a objetos).

yegor256
fuente
77
Getters y setters sugieren un modelo de dominio anémico.
Raedwald
77
Punto de vista interesante. Pero en la mayoría de los contextos de programación lo que necesitamos son estructuras de datos. Tomando el ejemplo del "perro" del artículo vinculado. Sí, no puede cambiar el peso de un perro del mundo real estableciendo un atributo ... pero a new Dog()no es un perro. Es un objeto que contiene información sobre un perro. Y para ese uso, es natural poder corregir un peso registrado incorrectamente.
Stephen C
3
Bueno, les digo que la mayoría de los programas útiles no necesitan modelar / simular objetos del mundo real. En mi opinión, no se trata realmente de lenguajes de programación. Se trata de para qué escribimos programas.
Stephen C
3
Mundo real o no, Yegor tiene toda la razón. Si lo que tiene es realmente una "Estructura" y no necesita escribir ningún código que haga referencia a él por nombre, colóquelo en una tabla hash u otra estructura de datos. Si necesita escribir código para él, póngalo como miembro de una clase y coloque el código que manipula esa variable en la misma clase y omita el setter y getter. PD. Aunque comparto principalmente el punto de vista de Yegor, he llegado a creer que los beans anotados sin código son estructuras de datos algo útiles; también los captadores a veces son necesarios, los establecedores nunca deberían existir.
Bill K
1
Me dejé llevar: toda esta respuesta, aunque correcta y relevante, no aborda la pregunta directamente. Tal vez debería decir "Tanto los establecedores / captadores Y las variables públicas están equivocados" ... Para ser absolutamente específicos, los Establecedores y las variables públicas grabables nunca deberían usarse, mientras que los captadores son más o menos lo mismo que las variables finales públicas y ocasionalmente son un mal necesario pero ninguno es mucho mejor que el otro.
Bill K
38

Una ventaja de los accesores y mutadores es que puede realizar la validación.

Por ejemplo, si foofuera público, podría configurarlo fácilmente nully luego alguien más podría intentar llamar a un método en el objeto. ¡Pero ya no está allí! Con un setFoométodo, podría asegurarme de que foonunca se haya configurado null.

Los accesores y los mutadores también permiten la encapsulación: si no se supone que ve el valor una vez que se establece (tal vez se establece en el constructor y luego se usa por métodos, pero nunca se debe cambiar), nadie lo verá nunca. Pero si puede permitir que otras clases lo vean o lo cambien, puede proporcionar el descriptor de acceso y / o mutador adecuado.

Thomas Owens
fuente
28

Depende de tu idioma. Usted ha etiquetado este "orientado a objetos" en lugar de "Java", por lo que me gustaría señalar que la respuesta de ChssPly76 depende del idioma. En Python, por ejemplo, no hay razón para usar getters y setters. Si necesita cambiar el comportamiento, puede usar una propiedad, que envuelve un captador y definidor alrededor del acceso básico a los atributos. Algo como esto:

class Simple(object):
   def _get_value(self):
       return self._value -1

   def _set_value(self, new_value):
       self._value = new_value + 1

   def _del_value(self):
       self.old_values.append(self._value)
       del self._value

   value = property(_get_value, _set_value, _del_value)
jcdyer
fuente
2
Sí, lo dije en un comentario debajo de mi respuesta. Java no es el único lenguaje que utiliza getters / setters como muleta, al igual que Python no es el único lenguaje capaz de definir propiedades. Sin embargo, el punto principal sigue siendo: "propiedad" no es el mismo "campo público".
ChssPly76
1
@jcd: para nada. Estás definiendo tu "interfaz" (API pública sería un término mejor aquí) exponiendo tus campos públicos. Una vez hecho eso, no hay vuelta atrás. Las propiedades NO son campos porque le brindan un mecanismo para interceptar los intentos de acceso a los campos (al enrutarlos a métodos si están definidos); esto es, sin embargo, nada más que el azúcar de sintaxis sobre los métodos getter / setter. Es extremadamente conveniente, pero no altera el paradigma subyacente: exponer los campos sin control sobre el acceso a ellos viola el principio de encapsulación.
ChssPly76
14
@ ChssPly76: no estoy de acuerdo. Tengo tanto control como si fueran propiedades, porque puedo convertirlas en propiedades cuando lo necesito. No hay diferencia entre una propiedad que usa getters y setters de repetitivo y un atributo sin formato, excepto que el atributo sin formato es más rápido, porque utiliza el lenguaje subyacente, en lugar de llamar a métodos. Funcionalmente, son idénticos. La única forma en que se podría violar la encapsulación es si crees que los paréntesis ( obj.set_attr('foo')) son inherentemente superiores a los signos iguales ( obj.attr = 'foo'). El acceso público es acceso público.
jcdyer
1
@jcdyer tiene tanto control sí, pero no tanta legibilidad, otros a menudo suponen erróneamente que obj.attr = 'foo'solo establece la variable sin que ocurra nada más
Timo Huovinen
99
@TimoHuovinen ¿En qué se diferencia eso de un usuario en Java suponiendo que obj.setAttr('foo')"solo establece la variable sin que ocurra nada más"? Si es un método público, entonces es un método público. Si lo usa para lograr algún efecto secundario, y es público, será mejor que pueda contar con que todo funcione como si solo sucediera ese efecto secundario previsto (con todos los demás detalles de implementación y otros efectos secundarios, uso de recursos, lo que sea , oculto de las preocupaciones del usuario). Esto no es absolutamente diferente con Python. La sintaxis de Python para lograr el efecto es simplemente más simple.
ely
25

Bueno, solo quiero agregar que incluso si a veces son necesarias para la encapsulación y la seguridad de sus variables / objetos, si queremos codificar un programa orientado a objetos real, entonces debemos DEJAR DE USAR LOS ACCESORIOS , porque a veces dependemos mucho sobre ellos cuando no es realmente necesario y eso hace casi lo mismo que si pusiéramos las variables públicas.

Jorge Aguilar
fuente
24

Gracias, eso realmente aclaró mi pensamiento. Ahora aquí hay (casi) 10 (casi) buenas razones para NO usar getters y setters:

  1. Cuando se da cuenta de que necesita hacer algo más que establecer y obtener el valor, puede hacer que el campo sea privado, lo que le dirá instantáneamente dónde ha accedido directamente.
  2. Cualquier validación que realice allí solo puede estar libre de contexto, cuya validación rara vez se practica.
  3. Puede cambiar el valor que se está configurando; esto es una pesadilla absoluta cuando la persona que llama le pasa un valor que [shock horror] quiere que almacene TAL CUAL.
  4. Puede ocultar la representación interna: fantástico, por lo que se asegura de que todas estas operaciones sean simétricas, ¿verdad?
  5. Ha aislado su interfaz pública de los cambios debajo de las hojas: si estaba diseñando una interfaz y no estaba seguro de si el acceso directo a algo estaba bien, entonces debería haber seguido diseñando.
  6. Algunas bibliotecas esperan esto, pero no muchas: la reflexión, la serialización, los objetos simulados funcionan bien con los campos públicos.
  7. Al heredar esta clase, puede anular la funcionalidad predeterminada; en otras palabras, puede REALMENTE confundir a las personas que llaman no solo ocultando la implementación sino haciéndola inconsistente.

Los tres últimos que acabo de dejar (N / A o D / C) ...

Apilado
fuente
11
Creo que el argumento crucial es que "si estaba diseñando una interfaz y no estaba seguro de si el acceso directo a algo estaba bien, entonces debería haber seguido diseñando". Ese es el problema más importante con getters / setters: reducen una clase a un simple contenedor de (más o menos) campos públicos. En OOP real , sin embargo, un objeto es más que un contenedor de campos de datos. Encapsula el estado y los algoritmos para manipular ese estado. Lo crucial de esta afirmación es que se supone que el estado está encapsulado y solo debe ser manipulado por los algoritmos proporcionados por el objeto.
sbi
22

Sé que es un poco tarde, pero creo que hay algunas personas que están interesadas en el rendimiento.

He hecho una pequeña prueba de rendimiento. Escribí una clase "NumberHolder" que, bueno, contiene un número entero. Puede leer ese número entero usando el método getter anInstance.getNumber()o accediendo directamente al número usando anInstance.number. Mi programa lee el número 1,000,000,000 de veces, en ambos sentidos. Ese proceso se repite cinco veces y se imprime el tiempo. Tengo el siguiente resultado:

Time 1: 953ms, Time 2: 741ms
Time 1: 655ms, Time 2: 743ms
Time 1: 656ms, Time 2: 634ms
Time 1: 637ms, Time 2: 629ms
Time 1: 633ms, Time 2: 625ms

(El tiempo 1 es el camino directo, el tiempo 2 es el captador)

Usted ve, el captador es (casi) siempre un poco más rápido. Luego lo intenté con diferentes números de ciclos. En lugar de 1 millón, utilicé 10 millones y 0.1 millones. Los resultados:

10 millones de ciclos:

Time 1: 6382ms, Time 2: 6351ms
Time 1: 6363ms, Time 2: 6351ms
Time 1: 6350ms, Time 2: 6363ms
Time 1: 6353ms, Time 2: 6357ms
Time 1: 6348ms, Time 2: 6354ms

Con 10 millones de ciclos, los tiempos son casi iguales. Aquí hay 100 mil (0.1 millones) ciclos:

Time 1: 77ms, Time 2: 73ms
Time 1: 94ms, Time 2: 65ms
Time 1: 67ms, Time 2: 63ms
Time 1: 65ms, Time 2: 65ms
Time 1: 66ms, Time 2: 63ms

También con diferentes cantidades de ciclos, el getter es un poco más rápido que la forma habitual. espero que esto te ayude.

kangalioo
fuente
3
Hay una sobrecarga "notable" que tiene una llamada a la función para acceder a la memoria en lugar de simplemente cargar la dirección de un objeto y agregar un desplazamiento para acceder a los miembros. Lo más probable es que la máquina virtual optimice su getter de todos modos. En cualquier caso, no vale la pena perder todos los beneficios de los captadores / establecedores.
Alex
16

No use getters setters a menos que sea necesario para su entrega actual Es decir, no piense demasiado en lo que sucederá en el futuro, si algo se cambia es una solicitud de cambio en la mayoría de las aplicaciones de producción, sistemas.

Piense simple, fácil, agregue complejidad cuando sea necesario.

No aprovecharía la ignorancia de los dueños de negocios con conocimientos técnicos profundos solo porque creo que es correcto o me gusta el enfoque.

Tengo un sistema masivo escrito sin getters setters solo con modificadores de acceso y algunos métodos para validar y realizar lógica de biz. Si realmente necesitabas el. Usa cualquier cosa.

Mohamed
fuente
16

Utilizamos getters y setters:

  • para la reutilización
  • para realizar la validación en etapas posteriores de la programación

Los métodos getter y setter son interfaces públicas para acceder a miembros de clases privadas.


Mantra de encapsulación

El mantra de encapsulación es hacer que los campos sean privados y los métodos públicos.

Métodos Getter: podemos obtener acceso a variables privadas.

Métodos de Setter: podemos modificar campos privados.

A pesar de que los métodos getter y setter no agregan nuevas funcionalidades, podemos cambiar de opinión y volver más tarde para hacer ese método

  • mejor;
  • más seguro y
  • Más rápido.

En cualquier lugar donde se pueda usar un valor, se puede agregar un método que devuelva ese valor. En vez de:

int x = 1000 - 500

utilizar

int x = 1000 - class_name.getValue();

En términos simples

Representación de la clase "Persona"

Supongamos que necesitamos almacenar los detalles de esto Person. Esto Persontiene los campos name, agey sex. Hacer esto implica la creación de métodos para name, agey sex. Ahora bien, si es necesario crear otra persona, se hace necesaria la creación de los métodos de name, age,sex todo de nuevo.

En lugar de hacer esto, podemos crear un bean class(Person)con métodos getter y setter. Así que mañana podemos crear objetos de este Bean class(Person class)siempre que necesitemos agregar una nueva persona (ver la figura). Por lo tanto, estamos reutilizando los campos y métodos de la clase bean, que es mucho mejor.

Devrath
fuente
15

Pasé bastante tiempo pensando en esto para el caso de Java, y creo que las razones reales son:

  1. Código para la interfaz, no la implementación
  2. Las interfaces solo especifican métodos, no campos

En otras palabras, la única forma en que puede especificar un campo en una interfaz es proporcionando un método para escribir un nuevo valor y un método para leer el valor actual.

Esos métodos son el famoso getter y setter ...

Thorbjørn Ravn Andersen
fuente
1
De acuerdo, segunda pregunta; en el caso de que sea un proyecto en el que no estás exportando fuente a nadie, y tienes el control total de la fuente ... ¿estás ganando algo con captadores y establecedores?
Dean J
2
En cualquier proyecto Java no trivial, debe codificar las interfaces para que las cosas sean manejables y comprobables (piense en maquetas y objetos proxy). Si usa interfaces, necesita getters y setters.
Thorbjørn Ravn Andersen
15

Puede ser útil para la carga diferida. Supongamos que el objeto en cuestión está almacenado en una base de datos y no desea obtenerlo a menos que lo necesite. Si un getter recupera el objeto, entonces el objeto interno puede ser nulo hasta que alguien lo solicite, entonces puede obtenerlo en la primera llamada al getter.

Tuve una clase de página base en un proyecto que se me entregó y que estaba cargando algunos datos de un par de llamadas de servicio web diferentes, pero los datos en esas llamadas de servicio web no siempre se usaron en todas las páginas secundarias. Los servicios web, para todos los beneficios, son pioneros en nuevas definiciones de "lento", por lo que no desea realizar una llamada al servicio web si no es necesario.

Me mudé de los campos públicos a los captadores, y ahora los captadores comprueban el caché, y si no está allí, llame al servicio web. Entonces, con un pequeño ajuste, se evitaron muchas llamadas de servicio web.

Entonces el captador me salva de tratar de descubrir, en cada página secundaria, lo que necesitaré. Si lo necesito, llamo al captador, y va a buscarlo si aún no lo tengo.

    protected YourType _yourName = null;
    public YourType YourName{
      get
      {
        if (_yourName == null)
        {
          _yourName = new YourType();
          return _yourName;
        }
      }
    }
Quillbreaker
fuente
Entonces, ¿el getter llama al setter?
icc97
He agregado una muestra de código de cómo lo hice en el pasado: esencialmente, almacena la clase real en un miembro protegido, luego devuelve ese miembro protegido en el get getor, inicializándolo si no está inicializado.
Quillbreaker
13

Un aspecto que me perdí en las respuestas hasta ahora, la especificación de acceso:

  • para los miembros, solo tiene una especificación de acceso para configurar y obtener
  • para setters y getters puede ajustarlo y definirlo por separado
jdehaan
fuente
13

EDITAR: Respondí esta pregunta porque hay un montón de personas que aprenden programación preguntando esto, y la mayoría de las respuestas son muy competentes técnicamente, pero no son tan fáciles de entender si eres un novato. Todos éramos novatos, así que pensé en probar una respuesta más amigable para los novatos.

Los dos principales son el polimorfismo y la validación. Incluso si es solo una estúpida estructura de datos.

Digamos que tenemos esta clase simple:

public class Bottle {
  public int amountOfWaterMl;
  public int capacityMl;
}

Una clase muy simple que contiene la cantidad de líquido que contiene y su capacidad (en mililitros).

¿Qué pasa cuando lo hago?

Bottle bot = new Bottle();
bot.amountOfWaterMl = 1500;
bot.capacityMl = 1000;

Bueno, no esperarías que eso funcione, ¿verdad? Desea que haya algún tipo de control de cordura. Y peor, ¿qué pasa si nunca especifiqué la capacidad máxima? Oh querido, tenemos un problema.

Pero también hay otro problema. ¿Qué pasaría si las botellas fueran solo un tipo de contenedor? ¿Qué pasaría si tuviéramos varios contenedores, todos con capacidades y cantidades de líquido lleno? Si pudiéramos hacer una interfaz, podríamos dejar que el resto de nuestro programa acepte esa interfaz, y las botellas, bidones y todo tipo de cosas simplemente funcionarían de manera intercambiable. ¿No sería eso mejor? Como las interfaces exigen métodos, esto también es algo bueno.

Terminaríamos con algo como:

public interface LiquidContainer {
  public int getAmountMl();
  public void setAmountMl(int amountMl);
  public int getCapacityMl();
}

¡Excelente! Y ahora solo cambiamos Botella a esto:

public class Bottle extends LiquidContainer {
  private int capacityMl;
  private int amountFilledMl;

  public Bottle(int capacityMl, int amountFilledMl) {
    this.capacityMl = capacityMl;
    this.amountFilledMl = amountFilledMl;
    checkNotOverFlow();
  }

  public int getAmountMl() {
    return amountFilledMl;
  }

  public void setAmountMl(int amountMl) {
     this.amountFilled = amountMl;
     checkNotOverFlow();
  }
  public int getCapacityMl() {
    return capacityMl;
  }

  private void checkNotOverFlow() {
    if(amountOfWaterMl > capacityMl) {
      throw new BottleOverflowException();
    }
}

Dejaré la definición de BottleOverflowException como un ejercicio para el lector.

Ahora note cuán más robusto es esto. Podemos lidiar con cualquier tipo de contenedor en nuestro código ahora aceptando LiquidContainer en lugar de Bottle. Y cómo estas botellas manejan este tipo de cosas puede diferir. Puede tener botellas que escriben su estado en el disco cuando cambia, o botellas que guardan en bases de datos SQL o GNU sabe qué más.

Y todo esto puede tener diferentes formas de manejar varios whoopsies. La botella solo comprueba y si se desborda, arroja una RuntimeException. Pero eso podría ser lo incorrecto. (Hay una discusión útil sobre el manejo de errores, pero lo mantengo muy simple a propósito. Las personas en los comentarios probablemente señalarán las fallas de este enfoque simplista.;))

Y sí, parece que pasamos de una idea muy simple a obtener respuestas mucho mejores rápidamente.

Tenga en cuenta también que no puede cambiar la capacidad de una botella. Ahora está en piedra. Podrías hacer esto con un int declarándolo final. Pero si se trata de una lista, puede vaciarla, agregarle cosas nuevas, etc. No puede limitar el acceso a tocar las entrañas.

También está la tercera cosa que no todos han abordado: los captadores y los establecedores usan llamadas a métodos. Eso significa que se ven como métodos normales en cualquier otro lugar. En lugar de tener una sintaxis específica extraña para DTO y otras cosas, tienes lo mismo en todas partes.

Haakon Løtveit
fuente
2
Gracias por la primera explicación medio decente de las interfaces que he leído, sin referencias a "controles remotos" o "automóviles"
djvs
1
"Puede tener botellas que escriben su estado en el disco cuando cambia, o botellas que guardan en las bases de datos SQL". Pero de todos modos, ¡buena idea presentarlo!
Xerus
10

En lenguajes que no admiten "propiedades" (C ++, Java) o requieren la recompilación de clientes al cambiar los campos a propiedades (C #), el uso de métodos get / set es más fácil de modificar. Por ejemplo, agregar lógica de validación a un método setFoo no requerirá cambiar la interfaz pública de una clase.

En los lenguajes que admiten propiedades "reales" (Python, Ruby, ¿quizás Smalltalk?) No tiene sentido obtener / establecer métodos.

John Millikin
fuente
1
Re: C #. Si agrega funcionalidad a un get / set, ¿eso no requeriría recompilación de todos modos?
steamer25
@ steamer25: lo siento, escribí mal. Quise decir que los clientes de la clase tendrán que volver a compilarse.
John Millikin
55
Agregar lógica de validación a un método setFoo no requerirá cambiar la interfaz de una clase a nivel de idioma , pero sí cambia la interfaz real , también conocida como contrato, porque cambia las condiciones previas. ¿Por qué querría uno que el compilador no trate eso como un cambio radical cuando lo es ?
R. Martinho Fernandes
@ R.MartinhoFernandes, ¿cómo se soluciona este problema "roto"? El compilador no puede decir si se está rompiendo o no. Esto es solo una preocupación cuando escribes bibliotecas para otros, ¡pero lo estás haciendo como zOMG universal, aquí están los dragones!
Phil
3
Requerir la compilación, como se menciona en la respuesta, es una forma en que el compilador puede informarle sobre un posible cambio importante. Y casi todo lo que escribo es efectivamente "una biblioteca para otros", porque no trabajo solo. Escribo código que tiene interfaces que usarán otras personas en el proyecto. ¿Cual es la diferencia? Demonios, incluso si voy a ser el usuario de esas interfaces, ¿por qué debería mantener mi código con estándares de calidad más bajos? No me gusta trabajar con interfaces problemáticas, incluso si soy yo quien las escribe.
R. Martinho Fernandes
6

Uno de los principios básicos del diseño OO: ¡Encapsulación!

Le brinda muchos beneficios, uno de los cuales es que puede cambiar la implementación del getter / setter detrás de escena, pero cualquier consumidor de ese valor continuará trabajando mientras el tipo de datos permanezca igual.

Justin Niessner
fuente
23
La oferta de captadores y colocadores de encapsulación es ridículamente delgada. Ver aquí .
sbi
Si su interfaz pública indica que 'foo' es de tipo 'T' y se puede configurar en cualquier cosa, nunca puede cambiar eso. Posteriormente, no puede decidir que sea del tipo 'Y', ni puede imponer reglas como restricciones de tamaño. Por lo tanto, si tiene get / set público que no hace mucho set / get, no está ganando nada que un campo público no ofrezca y lo hace más engorroso de usar. Si tiene una restricción, como que el objeto se puede establecer en nulo, o el valor debe estar dentro de un rango, entonces sí, se requeriría un método de establecimiento público, pero aún presenta un contrato para establecer este valor que puede ' t change
thecoshman
¿Por qué no puede cambiar un contrato?
Phil
55
¿Por qué deberían seguir compilando las cosas si cambian los contratos?
R. Martinho Fernandes
5

Debes usar getters y setters cuando:

  • Estás tratando con algo que es conceptualmente un atributo, pero:
    • Su idioma no tiene propiedades (o algún mecanismo similar, como los rastros variables de Tcl), o
    • El soporte de propiedad de su idioma no es suficiente para este caso de uso, o
    • Las convenciones idiomáticas de su idioma (o, a veces, su marco) alientan a los captadores o establecedores para este caso de uso.

Por lo tanto, rara vez es una pregunta general de OO; es una pregunta específica del idioma, con diferentes respuestas para diferentes idiomas (y diferentes casos de uso).


Desde el punto de vista de la teoría OO, los captadores y los establecedores son inútiles. La interfaz de su clase es lo que hace, no cuál es su estado. (Si no, ha escrito la clase incorrecta.) En casos muy simples, donde lo que hace una clase es, por ejemplo, representar un punto en coordenadas rectangulares, * los atributos son parte de la interfaz; getters y setters solo nublan eso. Pero en todo menos en casos muy simples, ni los atributos ni los captadores y definidores son parte de la interfaz.

Dicho de otra manera: si crees que los consumidores de tu clase ni siquiera deberían saber que tienes un spamatributo, y mucho menos ser capaz de cambiarlo de manera involuntaria, entonces darles un set_spammétodo es lo último que quieres hacer.

* Incluso para esa clase simple, es posible que no desee permitir establecer los valores xy y. Si esto es realmente una clase, que no debería tener métodos como translate, rotate, etc.? Si es solo una clase porque su lenguaje no tiene registros / estructuras / tuplas con nombre, entonces esto no es realmente una cuestión de OO ...


Pero nadie está haciendo un diseño general de OO. Están haciendo diseño e implementación en un lenguaje específico. Y en algunos idiomas, getters y setters están lejos de ser inútiles.

Si su lenguaje no tiene propiedades, entonces la única forma de representar algo que es conceptualmente un atributo, pero que en realidad se calcula, o se valida, etc., es a través de getters y setters.

Incluso si su idioma tiene propiedades, puede haber casos en los que sean insuficientes o inapropiados. Por ejemplo, si desea permitir que las subclases controlen la semántica de un atributo, en idiomas sin acceso dinámico, una subclase no puede sustituir una propiedad calculada por un atributo.

En cuanto a "¿y si quiero cambiar mi implementación más tarde?" pregunta (que se repite varias veces en diferentes palabras tanto en la pregunta del OP como en la respuesta aceptada): si realmente es un cambio de implementación puro, y usted comenzó con un atributo, puede cambiarlo a una propiedad sin afectar la interfaz. A menos que, por supuesto, su idioma no lo admita. Así que este es realmente el mismo caso nuevamente.

Además, es importante seguir los modismos del lenguaje (o marco) que está utilizando. Si escribe un hermoso código de estilo Ruby en C #, cualquier desarrollador experimentado de C # que no sea usted tendrá problemas para leerlo, y eso es malo. Algunos lenguajes tienen culturas más fuertes en torno a sus convenciones que otros. Y puede que no sea una coincidencia que Java y Python, que se encuentran en extremos opuestos del espectro por lo idiomáticos que son los captadores, tengan dos de las culturas más fuertes.

Más allá de los lectores humanos, habrá bibliotecas y herramientas que esperan que sigas las convenciones y te hagan la vida más difícil si no lo haces. Conectar widgets de Interface Builder a cualquier cosa que no sean las propiedades de ObjC, o usar ciertas bibliotecas de burla de Java sin getters, simplemente te está haciendo la vida más difícil. Si las herramientas son importantes para ti, no luches contra ellas.

abarnert
fuente
4

Desde el punto de vista del diseño de orientación a objetos, ambas alternativas pueden ser perjudiciales para el mantenimiento del código al debilitar la encapsulación de las clases. Para una discusión, puede consultar este excelente artículo: http://typicalprogrammer.com/?p=23

andrers52
fuente
3

Los métodos getter y setter son métodos de acceso, lo que significa que generalmente son una interfaz pública para cambiar los miembros de la clase privada. Utiliza métodos getter y setter para definir una propiedad. Accede a los métodos getter y setter como propiedades fuera de la clase, aunque los defina dentro de la clase como métodos. Esas propiedades fuera de la clase pueden tener un nombre diferente del nombre de la propiedad en la clase.

El uso de métodos getter y setter tiene algunas ventajas, como la capacidad de permitirle crear miembros con funcionalidades sofisticadas a las que puede acceder como propiedades similares. También le permiten crear propiedades de solo lectura y de solo escritura.

Aunque los métodos getter y setter son útiles, debe tener cuidado de no usarlos en exceso porque, entre otros problemas, pueden dificultar el mantenimiento del código en ciertas situaciones. Además, proporcionan acceso a la implementación de su clase, como los miembros públicos. La práctica de OOP desalienta el acceso directo a las propiedades dentro de una clase.

Cuando escribe clases, siempre se le recomienda que haga privadas la mayor cantidad posible de sus variables de instancia y que agregue métodos getter y setter en consecuencia. Esto se debe a que hay varias ocasiones en las que es posible que no desee que los usuarios cambien ciertas variables dentro de sus clases. Por ejemplo, si tiene un método estático privado que rastrea el número de instancias creadas para una clase específica, no desea que un usuario modifique ese contador utilizando el código. Solo la declaración del constructor debe incrementar esa variable siempre que se llame. En esta situación, puede crear una variable de instancia privada y permitir un método getter solo para la variable counter, lo que significa que los usuarios pueden recuperar el valor actual solo mediante el método getter, y no podrán establecer nuevos valores utilizando el método setter.

Sumit Singh
fuente
3

El código evoluciona . privatees ideal para cuando necesita protección de miembros de datos . Eventualmente, todas las clases deberían ser una especie de "miniprogramas" que tienen una interfaz bien definida que no se puede simplemente atornillar con lo interno .

Dicho esto, el desarrollo de software no se trata de establecer esa versión final de la clase como si estuvieras presionando alguna estatua de hierro fundido en el primer intento. Mientras trabajas con él, el código es más como arcilla. Evoluciona a medida que lo desarrollas y aprendes más sobre el dominio del problema que estás resolviendo. Durante el desarrollo, las clases pueden interactuar entre sí de lo que deberían (dependencia que planea descontar), fusionarse o separarse. Así que creo que el debate se reduce a personas que no quieren escribir religiosamente

int getVar() const { return var ; }

Así que tienes:

doSomething( obj->getVar() ) ;

En vez de

doSomething( obj->var ) ;

No solo es getVar()visualmente ruidoso, sino que da la ilusión de que de gettingVar()alguna manera es un proceso más complejo de lo que realmente es. La forma en que usted (como escritor de la clase) considera que la santidad vares particularmente confusa para un usuario de su clase si tiene un setter passthru, entonces parece que está poniendo estas puertas para "proteger" algo que insiste es valioso, (la santidad de var), pero aun así usted reconoce que varla protección no vale mucho por la capacidad de cualquiera de entrar yset var al valor que quiera, sin siquiera mirar lo que están haciendo.

Así que programo de la siguiente manera (suponiendo un enfoque de tipo "ágil", es decir, cuando escribo código sin saber exactamente lo que hará / no tengo tiempo o experiencia para planificar un elaborado conjunto de interfaces de estilo cascada):

1) Comience con todos los miembros públicos para objetos básicos con datos y comportamiento. Es por eso que en todo mi código de "ejemplo" de C ++ me notarás usando en structlugar de en classtodas partes.

2) Cuando el comportamiento interno de un objeto para un miembro de datos se vuelve lo suficientemente complejo (por ejemplo, le gusta mantener un interno std::listen algún tipo de orden), se escriben las funciones de tipo de acceso. Debido a que estoy programando solo, no siempre establezco el miembro de privateinmediato, pero en algún momento de la evolución de la clase, el miembro será "promovido" a uno protectedu otro private.

3) Las clases que están completamente desarrolladas y tienen reglas estrictas sobre sus componentes internos (es decir , saben exactamente lo que están haciendo, y no debe "joder" (término técnico) con sus classcomponentes internos) reciben la designación, miembros privados predeterminados, y solo unos pocos miembros selectos pueden ser public.

Creo que este enfoque me permite evitar sentarme allí y escribir religiosamente getter / setters cuando muchos miembros de datos se migran, cambian de lugar, etc. durante las primeras etapas de la evolución de una clase.

bobobobo
fuente
1
"... una interfaz bien definida que no se puede simplemente atornillar con los elementos internos" y la validación en los setters.
Agi Hammerthief
3

Hay una buena razón para considerar el uso de accesores si no hay herencia de propiedad. Ver siguiente ejemplo:

public class TestPropertyOverride {
    public static class A {
        public int i = 0;

        public void add() {
            i++;
        }

        public int getI() {
            return i;
        }
    }

    public static class B extends A {
        public int i = 2;

        @Override
        public void add() {
            i = i + 2;
        }

        @Override
        public int getI() {
            return i;
        }
    }

    public static void main(String[] args) {
        A a = new B();
        System.out.println(a.i);
        a.add();
        System.out.println(a.i);
        System.out.println(a.getI());
    }
}

Salida:

0
0
4
GeZo
fuente
3

Getters y setters se utilizan para implementar dos de los aspectos fundamentales de la Programación Orientada a Objetos que son:

  1. Abstracción
  2. Encapsulamiento

Supongamos que tenemos una clase de empleado:

package com.highmark.productConfig.types;

public class Employee {

    private String firstName;
    private String middleName;
    private String lastName;

    public String getFirstName() {
      return firstName;
    }
    public void setFirstName(String firstName) {
       this.firstName = firstName;
    }
    public String getMiddleName() {
        return middleName;
    }
    public void setMiddleName(String middleName) {
         this.middleName = middleName;
    }
    public String getLastName() {
        return lastName;
    }
    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public String getFullName(){
        return this.getFirstName() + this.getMiddleName() +  this.getLastName();
    }
 }

Aquí los detalles de implementación del Nombre completo están ocultos para el usuario y no son accesibles directamente para el usuario, a diferencia de un atributo público.

Pritam Banerjee
fuente
1
Para mí, tener toneladas de getters y setters que no hacen nada único es inútil. getFullName es una excepción porque hace algo más. Tener solo las tres variables públicas y mantener getFullName hará que el programa sea más fácil de leer, pero aún tendrá oculto ese nombre completo. En general, estoy completamente bien con getters y setters si a. hacen algo único y / o b. solo tienes uno, sí, podrías tener una final pública y todo eso, pero no
FacelessTiger
1
El beneficio de esto es que puede cambiar las partes internas de la clase, sin cambiar la interfaz. Digamos que, en lugar de tres propiedades, tenía una: una serie de cadenas. Si ha estado usando getters y setters, puede hacer ese cambio y luego actualizar getter / setters para saber que nombres [0] es el primer nombre, nombres [1] es el medio, etc. Pero si solo usó propiedades públicas , también debería cambiar cada clase a la que accedió Empleado, porque la propiedad firstName que han estado usando ya no existe.
Andrew Hows
1
@AndrewHows de lo que he visto en la vida real, cuando las personas cambian los elementos internos de la clase también cambian la interfaz y hacen una gran refactorización de todo el código
Eildosa
2

Otro uso (en lenguajes que admiten propiedades) es que los establecedores y captadores pueden implicar que una operación no es trivial. Por lo general, desea evitar hacer algo que sea computacionalmente costoso en una propiedad.

Jason Baker
fuente
Nunca esperaría que un getter o setter fuera una operación costosa. En tales casos, un mejor uso de una fábrica: utilizar todos los emisores que necesita y luego invocar la cara executeo buildmétodo.
Hubert Grzeskowiak
2

Una ventaja relativamente moderna de los captadores / establecedores es que facilita la exploración del código en editores de código etiquetados (indexados). Por ejemplo, si desea ver quién establece un miembro, puede abrir la jerarquía de llamadas del establecedor.

Por otro lado, si el miembro es público, las herramientas no permiten filtrar el acceso de lectura / escritura al miembro. Por lo tanto, debe caminar a través de todos los usos del miembro.

Rakesh Singh
fuente
puede hacer clic con el botón derecho> buscar uso en un miembro exactamente como en un getter / setter
Eildosa
2

En un lenguaje orientado a objetos, los métodos y sus modificadores de acceso declaran la interfaz para ese objeto. Entre el constructor y los métodos de acceso y mutación, es posible que el desarrollador controle el acceso al estado interno de un objeto. Si las variables simplemente se declaran públicas, entonces no hay forma de regular ese acceso. Y cuando usamos setters podemos restringir al usuario para la entrada que necesitamos. Significa que el feed para esa variable muy vendrá a través de un canal apropiado y el canal está predefinido por nosotros. Por lo tanto, es más seguro usar setters.

Antz
fuente
1

Además, esto es para "preparar el futuro" de su clase. En particular, cambiar de un campo a una propiedad es una ruptura de ABI, por lo que si luego decide que necesita más lógica que simplemente "establecer / obtener el campo", entonces necesita romper ABI, lo que por supuesto crea problemas para cualquier cosa más ya compilado contra su clase.

Pete
fuente
2
Supongo que cambiar el comportamiento del getter o setter no es un cambio radical entonces. </sarcasm>
R. Martinho Fernandes
@ R.MartinhoFernandes no siempre tiene que ser así. TBYS
Phil
1

Solo me gustaría lanzar la idea de la anotación: @getter y @setter. Con @getter, debería poder obj = class.field pero no class.field = obj. Con @setter, viceversa. Con @getter y @setter deberías poder hacer ambas cosas. Esto preservaría la encapsulación y reduciría el tiempo al no llamar a métodos triviales en tiempo de ejecución.

fastcodejava
fuente
1
Se implementaría en tiempo de ejecución con "métodos triviales". En realidad, probablemente no trivial.
Phil
Hoy esto se puede hacer con un preprocesador de anotaciones.
Thorbjørn Ravn Andersen