getters - set y get c++
Get/Set en el mundo c++, faux-pas? (12)
Observé que get / set no es el modo c ++ en lo que puedo decir mirando en boost / stl, e incluso leyendo las escrituras de algunos de los mejores expertos en c ++.
¿Alguien usa get / set en su diseño de clase de c ++, y alguien puede sugerir una regla empírica sobre dónde, si este paradigma pertenece en el mundo c ++?
Obviamente, es muy popular en Java e imitado por c # usando el azúcar sintáctico de la propiedad.
EDITAR:
Después de leer más sobre esto en uno de los enlaces proporcionados en la respuesta a continuación, encontré al menos un argumento para mantener los descriptores de acceso de un campo miembro con el mismo nombre que el campo de miembro. A saber, que simplemente podría exponer el campo miembro como público y, en su lugar, convertirlo en una instancia de una clase y luego sobrecargar al operador (). Al utilizar set / get, obligaría a los clientes a no solo a recompilar, sino también a cambiar su código.
No estoy seguro de que me encanta la idea, me parece un poco demasiado fina, pero hay más detalles aquí:
Definitivamente puede usar accesadores en C ++. Este es un buen artículo sobre la presentación de buenos esquemas de acceso. Un artículo relacionado también le muestra una clase simple de asistente de meta acceso para ayudarlo a definir estos accesores inteligentes trivialmente.
La encapsulación es un concepto de OOP y se aplica a todos los lenguajes de OOP. Los miembros de datos públicos romperían la encapsulación. Esto puede estar bien si tiene un objeto muy simple que no necesita encapsulamiento, sin embargo esas situaciones son la excepción y una vez que toma la decisión puede ser difícil regresar y deshacerla.
Para la mayoría de los objetos, querrás tener getters y setters, pero siempre debes considerar cómo se usará realmente el objeto cuando los escribas. Boost y STL están llenos de getters y setters, simplemente no usan los nombres "get" y "set", sino que usan nombres como "length", "end", "reserve", "capacity", etc. La razón por la que no use las palabras get o set es porque estas funciones tienen un propósito mayor que el de establecer un valor en el objeto.
Tus getters y setters deberían hacer lo mismo. En lugar de diseñar la interfaz en términos de cómo funciona un objeto, debe definirlo en términos de cómo se usará.
No sé si es uso recomendado o no, pero utilizo funciones get / set en mis clases de C ++ regularmente, y he estado escribiendo código C ++ durante más de dos décadas. Nunca miré Java o C #, así que no recogí el hábito de esos idiomas.
Tiendo a tener getters y setters, simplemente no tiendo a llamarlos "getX and" setX ", generalmente haré algo como esto por ejemplo:
int x = o->x() // getter
o->setX(5); // setter
Me parece que tener el captador simplemente sea el nombre de la "propiedad" simplemente se lee mejor.
Voy a tomar algunas conjeturas.
- C ni siquiera tenía la posibilidad de getters / setters, por lo que había una costumbre de usar acceso directo a los miembros, como en una estructura. El hábito atrapado en C ++.
- C / C ++ siempre ha favorecido la velocidad, y si hubiera alguna posibilidad de que un viejo compilador no se alineara correctamente, un getter / setter tendría una penalización de velocidad.
Ninguno de estos son razones convincentes.
En general, los métodos get / set subvierten la encapsulación al exponer la implementación interna y el estado. Si se encuentra utilizando get / set en cada pieza de datos en su clase, lo más probable es que sea simplemente un tipo agregado simple con solo datos públicos y sin métodos.
Realmente no compro que get / set hace que sea más fácil hacer cosas como, por ejemplo, hacer que tu clase sea segura para los subprocesos, porque la sincronización limitada que puedes proporcionar protege contra todos los tipos incorrectos de condiciones de carrera.
Solo uso getters / setters cuando no hay alternativa. Cuando puedo, utilizo este patrón (no en el sentido de que sea una buena práctica, sino en el sentido de que lo hago de manera consistente): cambiar una propiedad no afecta el comportamiento del objeto hasta que realmente se necesita. Por ejemplo:
myWnd->Title = "hello"; // not a setter, just a LPCSTR member
myWnd->Title = "world";
myWnd->ShowWindow(); // perhaps updates a WNDCLASS structure
// and other complicated things that
// the user of the class doesn''t want to know
Sé que esto significa que tendré que escribir algunos métodos privados artificiales para actualizar los estados internos de los objetos, pero si se necesita ese esfuerzo para ocultar la complejidad al usuario de la clase, tendré que hacerlo.
Casi siempre uso métodos get / set, principalmente porque puede establecer puntos de interrupción en ellos y averiguar dónde se está configurando (o accediendo) un miembro de datos, aunque esto es menos común. Además, puede agregar aserciones de depuración dentro de la rutina setter (y la rutina getter, aunque esto es menos útil) para asegurarse de que el objeto esté en un estado válido al establecer el valor.
También es útil si creas una subclase; a veces la subclase quiere hacer algunos cálculos en lugar de simplemente ajustar el valor. Hacer que la rutina getter sea virtual y luego anularla en la subclase lo hace fácil.
Mi experiencia es a través de C ++ y Java, aunque hoy en día estoy trabajando en PHP. Mis reglas generales que uso para PHP y C ++ son:
Si necesita que una variable miembro sea legible desde fuera de la clase pero no se pueda escribir: use getVariableX () solamente.
Si desea permitir que las variables miembro sean alteradas / leídas fuera de la clase, pero necesita trabajo adicional realizado antes / después de que se cambien sus valores: use setVariableX () y getVariableX ().
Si una variable miembro puede ser alterada desde fuera de la clase y los métodos set / get simplemente serían una tarea simple: simplemente haz pública la variable, ya que eso es lo que harías de todos modos con set / gets (solo de una manera más ofuscada).
Tenga en cuenta que si sus métodos get y set hacen mucho más que obtener y configurar de manera trivial, entonces probablemente debería cambiarles el nombre para describir con mayor precisión su función.
Va a ser un poco didáctico aquí ...
Hay dos aspectos para los usuarios:
- Trabajando dentro de la sintaxis del lenguaje
- Intento de comunicación
También hay un tercer aspecto que a menudo se ignora, y que tiene que ver con el manejo del cambio con gracia. Mi artículo que enlazas para abordar este último punto, pero no te dice nada sobre los otros dos.
Intentar manejar el cambio dentro de la sintaxis del idioma que está utilizando es principalmente un problema técnico, que es susceptible de algunos consejos reunidos en una página web con un poco de código para respaldarlo.
El aspecto más difícil es comunicar la intención y la forma de hacerlo es seguir con las expresiones idiomáticas del idioma. Desafortunadamente en C ++ la sintaxis se interpone en el camino de este modo, así que tenemos cosas como .size () en las colecciones y .first y .second en los pares. Todos son accesadores, pero la sintaxis cambia dependiendo de la implementación - ouch.
Ahora, eJames habla de miembros públicos rompiendo la encapsulación. Si un miembro es público o no, no tiene nada que ver con la encapsulación. La encapsulación es un producto del diseño de los objetos y de los controles disponibles para el diseñador de la clase dentro del lenguaje que está utilizando. Esto es algo que exploré con más profundidad en "Encapsulation is a Good Thing ™" (este sitio no me deja agregar un enlace todavía, pero supongo que no es demasiado difícil para Google).
Lo que nos deja es que en C ++ un atributo derivado debe usar la sintaxis de invocación del método. Un campo no derivado no tiene que serlo, pero puede elegir si así lo desea. Si utiliza la sintaxis de invocación del método, debe escribir usted mismo el método de envoltura. No es difícil, pero sin duda se suma al conteo de líneas. Lo que traté de mostrar fue una forma de usar el lenguaje de plantilla de C ++ para abstraer el código de acceso. No es totalmente exitoso, pero maneja muchos casos de uso.
En cuanto a si deberíamos usar accesores o no, el problema es que la sintaxis de C ++ obliga a la distinción entre acceso de miembro simple y acceso a métodos como desarrolladores. Esto es molesto, pero tenemos algunas herramientas para hacer algo al respecto.
Como desarrollador de bibliotecas, he descubierto que usar siempre la sintaxis de invocación de métodos me ayuda a crear API más robustas, porque si encuentro que quiero reemplazar un miembro simple con algo más complejo, entonces me da más opciones que no requieren bastante mucha sintaxis Recuerda, podría abstraer para el otro lado y hacer que una "función" parezca un valor mediante el uso adecuado de los operadores de reparto y operadores de asignación, tal vez lo intente y vea cómo me siento al respecto :)
Incluso si c ++ no admite acceso a propiedades simulando, no solo mejoramos la legibilidad o proporcionamos encapsulamiento, sino que proporcionamos un mecanismo de control para establecer un valor a una variable u obtenemos un valor calculado para una variable. Este es el objetivo final de los usuarios. Para alcanzar estos objetivos, el idioma necesario necesariamente es compatible con los usuarios directamente. Período.
C ++ no tiene propiedades como C #. Es posible escribir métodos con "get" y "set" en sus nombres, pero no crean propiedades automáticamente. Entonces, ¿es una buena práctica usar los métodos get y set entonces?
Usar los métodos get y set en C ++ no es malo para acceder a las propiedades de la clase. El STL y el impulso (que fue influenciado por el STL) simplemente eligieron un diseño; está perfectamente bien tener un diseño diferente para sus clases.
En mi trabajo, usamos get y set. La razón es principalmente que hace posible escribir analizadores para envolver automáticamente las clases de C ++ mediante otras interfaces: ActiveX, .NET, LabVIEW, Python, etc. ... cuando se usa la intellisencia de Visual Studio (y tecnologías similares en otros IDEs) , Encuentro que usar los métodos get y set hace que encontrar lo que soy sea más fácil. Entonces, hay ocasiones en que es beneficioso usar los métodos de obtención y establecimiento.
Lo más importante es elegir un estándar de estilo de código para su biblioteca y ser consecuente con él.