¿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.
Respuestas:
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:
fuente
public
mé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), lospublic
accesos 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/59087plane.turnTo(dir); plane.setSpeed(spd); plane.setTargetAltitude(alt); plane.getBreaks().release();
querer decirplane.takeOff(alt)
. Los campos de datos internos que deben cambiarse para poner el avión en eltakingOff
modo no son de mi incumbencia. Y qué otros objetos (breaks
) notifica el método tampoco quiero saber.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 :-)
fuente
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:
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.
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 ).
fuente
private
campo. Si una clase no tiene setters, es fácil hacerla inmutable.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:
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.
fuente
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.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:
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 :)
fuente
while(speed < 200) { do_something(); accelerate(); }
)myCar.setSpeed(157);
y después de algunas líneasspeed = myCar.getSpeed();
Y ahora ... Les deseo una feliz depuración mientras trato de entender por quéspeed==100
cuándo debería ser157
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).
fuente
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.Una ventaja de los accesores y mutadores es que puede realizar la validación.
Por ejemplo, si
foo
fuera público, podría configurarlo fácilmentenull
y luego alguien más podría intentar llamar a un método en el objeto. ¡Pero ya no está allí! Con unsetFoo
método, podría asegurarme de quefoo
nunca se haya configuradonull
.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.
fuente
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:
fuente
obj.set_attr('foo')
) son inherentemente superiores a los signos iguales (obj.attr = 'foo'
). El acceso público es acceso público.obj.attr = 'foo'
solo establece la variable sin que ocurra nada másobj.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.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.
fuente
Gracias, eso realmente aclaró mi pensamiento. Ahora aquí hay (casi) 10 (casi) buenas razones para NO usar getters y setters:
Los tres últimos que acabo de dejar (N / A o D / C) ...
fuente
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 usandoanInstance.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:(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:
Con 10 millones de ciclos, los tiempos son casi iguales. Aquí hay 100 mil (0.1 millones) ciclos:
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.
fuente
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.
fuente
Utilizamos getters y setters:
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.
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
En cualquier lugar donde se pueda usar un valor, se puede agregar un método que devuelva ese valor. En vez de:
utilizar
En términos simples
Supongamos que necesitamos almacenar los detalles de esto
Person
. EstoPerson
tiene los camposname
,age
ysex
. Hacer esto implica la creación de métodos paraname
,age
ysex
. Ahora bien, si es necesario crear otra persona, se hace necesaria la creación de los métodos dename
,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 Beanclass(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.fuente
Pasé bastante tiempo pensando en esto para el caso de Java, y creo que las razones reales son:
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 ...
fuente
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.
fuente
Un aspecto que me perdí en las respuestas hasta ahora, la especificación de acceso:
fuente
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:
Una clase muy simple que contiene la cantidad de líquido que contiene y su capacidad (en mililitros).
¿Qué pasa cuando lo hago?
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:
¡Excelente! Y ahora solo cambiamos Botella a esto:
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.
fuente
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.
fuente
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.
fuente
Debes usar getters y setters cuando:
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
spam
atributo, y mucho menos ser capaz de cambiarlo de manera involuntaria, entonces darles unset_spam
método es lo último que quieres hacer.* Incluso para esa clase simple, es posible que no desee permitir establecer los valores
x
yy
. Si esto es realmente una clase, que no debería tener métodos comotranslate
,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.
fuente
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
fuente
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.
fuente
El código evoluciona .
private
es 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
Así que tienes:
En vez de
No solo es
getVar()
visualmente ruidoso, sino que da la ilusión de que degettingVar()
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 santidadvar
es 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 devar
), pero aun así usted reconoce quevar
la 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
struct
lugar de enclass
todas 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::list
en algún tipo de orden), se escriben las funciones de tipo de acceso. Debido a que estoy programando solo, no siempre establezco el miembro deprivate
inmediato, pero en algún momento de la evolución de la clase, el miembro será "promovido" a unoprotected
u otroprivate
.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
class
componentes internos) reciben la designación, miembros privados predeterminados, y solo unos pocos miembros selectos pueden serpublic
.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.
fuente
Hay una buena razón para considerar el uso de accesores si no hay herencia de propiedad. Ver siguiente ejemplo:
Salida:
fuente
Getters y setters se utilizan para implementar dos de los aspectos fundamentales de la Programación Orientada a Objetos que son:
Supongamos que tenemos una clase de empleado:
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.
fuente
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.
fuente
execute
obuild
método.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.
fuente
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.
fuente
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.
fuente
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.
fuente