2010-11-06 22 views
6

A veces tengo que exponer algunos de los miembros de la clase. Por ejemplo, en el siguiente ejemplo, class Mechanic puede necesitar acceso directo al componente Engine. He leído muchas veces que se debe acceder a todos los campos mediante métodos de mutador (acceso) debido a varias razones. Pero ¿hay alguna ventaja en la prestación de captador de referencia no const:¿Tiene sentido proporcionar getter de referencia no const

class Car 
{ 
    public: 
     Engine & engine() 
     { 
      return m_engine; 
     } 

     //as a consequence you will also need to provide const version 
     const Engine & engine() const 
     { 
      return m_engine; 
     } 

    private: 
     Engine m_engine; 
} 

sobre pública componente del motor simplemente haciendo:

class Car 
{ 
    public: 
     Engine engine; 
} 

También puede reemplazar con publicprotected si no te gusta este ejemplo. En la vida real tiene algo simillar en Java cuando se trata de System.in o System.out. Parece que, para ser totalmente compatible con lo que algunas personas dicen, necesitarías realizar llamadas como System.getInstance().getOut().println("hello world"). No veo ningún beneficio excepto un montón de código burocrático en tales casos.

+0

No hay votación cerrada, pero si el propósito de la pregunta es establecer una teoría y luego estar en desacuerdo con todas las respuestas contrarias a esa teoría, entonces es probable que sea "subjetiva y argumentativa". Si su teoría es correcta o incorrecta. –

+0

@Steve Jessop: No seas tan celoso, ordena las preguntas por votos y obtendrás muchas inexactas (la pregunta no puede ser subjetiva, la respuesta puede ser). Cada respuesta es más o menos subjetiva. Como excusa de sus sospechas, estaba en un viaje y no he tenido la oportunidad de visitar Stackoverflow últimamente. – doc

+0

es por eso que no estoy seguro. Si alguien realmente está pidiendo razones para algo, creo que está bien, aunque no haya una razón definitiva. Si alguien no cree que hay razones, pero de todos modos pregunta por qué, creo que "generalmente conduce a la confrontación y la discusión". No se produce ningún daño grave de ninguna manera, pero este no es el propósito del sitio AFAIK. –

Respuesta

1

He encontrado un punto razonable para proporcionar tal getter. Facilita la integración de su software (por ejemplo, cuando desea traducir la interfaz a otro idioma y enlazar ABI).

3

Pueden ser útiles cuando el valor que está devolviendo está realmente en el montón.

template<class T> class Singleton 
{ 
private: 
    static T* m_pSingleton; 

public: 
    T& getSingleton() { assert(m_pSingleton); return(*m_pSingleton); }; 

}; // eo class Singleton 
+3

Definitivamente downvoting para el patrón de Singleton. – Puppy

+2

Ah, recuerdo los momentos en que el patrón Singleton estaba de moda ... Diablos, incluso recuerdo cuando PEEK y POKE estaban de moda. :-) – Gorgen

+4

Sí, las matrices son malvadas, los getters y setters son malvados, singletons son malvados, toda la programación es malvada. Los mejores programadores son aquellos que no escribieron un código. +1 porque los singletons a veces son útiles. – doc

0

Para mí tiene sentido aquí:

image(i,j) = 234; 
1

Una ventaja de proporcionar un captador es que cuando y si se decide cambiar la forma en que funciona getter, el código que utiliza esta clase no tiene por qué ser recompilado Pero si tiene un campo público y luego decide hacer un getter, todo el código debe ser recompilado. Aparte de eso, no veo ninguna razón práctica seria para hacer que tu variable sea privada. Sin embargo, tenga en cuenta que todo esto se cumple si y solo si debe proporcionar una forma para que los usuarios externos obtengan una referencia al Motor. Si es posible diseñar el software para que esto se elimine del todo, sería mejor.

+1

Si proporciona un campo, y luego cambia a un getter, el código del cliente no solo tiene que ser recompilado, sino que debe ser reescrito. –

3

Buscadores y establecedores explícitos puede ser excesivamente burocrático; Eso depende de tu situacion.

La principal razón para tener funciones getter y setter es que aísla a los clientes de su clase de posibles cambios en la implementación en el futuro (por ejemplo, considere qué pasaría si usted decide generar un objeto Engine a pedido (en lugar de usar una variable miembro), o decide ocultarlo detrás de un puntero inteligente o de algún otro contenedor).

Si su clase es muy simple (por ejemplo, cerca de ser POD) y es poco probable que cambie, puede que no valga la pena tener que implementar getters y setters.

Sin embargo, para responder a su pregunta, un getter no const probablemente no tenga mucho sentido. Su prototipo getter debe ser Engine & engine() const; de lo contrario, no podrá llamarlo al constCar objetos.

+1

Para una mejor búsqueda en Google, esto se llama * encapsulación *. –

+1

He arreglado el ejemplo. Habrá dos versiones del método 'engine()': const y non-const. En mi opinión, a veces es conveniente exponer a los miembros y retirar la encapsulación. – doc

0

En lugar de pensar en exponer a miembros privados de una clase, piense más en las líneas de métodos de llamadas en esas clases. Leí un interesante artículo de Java, Why Getter and Setter Methods are Evil, que se aplica tanto a C++ como a Java.

+0

Sí, lo he leído y escribí el comentario titulado "La teoría es solo teoría" :) Mi punto es que el código consiste en operaciones y datos, no solo en el código. De alguna manera tienes que modificar los datos para que el artículo esté obviamente mal. El autor no ve la gran imagen detrás de la informática. Se ha metido en algunos principios construidos en su parte superior, llamados Programación Orientada a Objetos. Pero OOP no existe sin programación procedimental. – doc

+0

@doc: Si es inútil, ¿por qué preocuparse por lo que dice la teoría en primer lugar? En lo que respecta a los patrones de la computadora, la teoría no es un concepto matemático abstracto que evoca un soñador de día (Lea "Los primeros patrones de diseño de la cabeza" sobre esto). Nacen de la necesidad (debido a problemas enfrentados en la práctica). Tu problema es uno de ellos. Entonces, cuando alguien dice "Getters y setters son malos", no es como decir "1 == 1". – nakiya

1

Como me enteré de que me educaron recientemente, los buscadores y los incubadores huelen a mal diseño.Pero, si lo desea de esa manera, proporcionar funciones para obtener y configurar m_engine (definido por usted) en lugar de simplemente exponerlo (no tiene intervención) significa que tiene un punto de complemento para cambios futuros.

+0

¿Cómo se puede implementar, digamos, 'clase Window' con su ancho, alto y algunas otras propiedades sin getters ni setters? ¿No nos estamos volviendo locos? La mayoría de los objetos de la vida real son como 'clase Window'; estructuras casi simples llenas de algunos métodos. Conocí el diseño con pocos accesorios (aunque 'Window' tiene sus métodos' GetWidth' o 'GetSize') en forma de biblioteca SFML y por eso no pude extender bien sus clases. – doc

+0

Hubo dos puntos en mi respuesta. El primero es: la encapsulación es buena. El segundo es que si no puede tener el primero, entonces los getters y setters son buenos. La idea en el segundo escenario es evitar la duplicación de código que pueda ocurrir en el futuro (o en este momento) si desea aplicar alguna restricción en el ancho o alto de 'Window '. En el primer punto, mientras que los setters pueden excusarse un poco, ¿por qué necesitas getters? ¿No significa eso que prefieres tener ese bit de datos que el captador está exponiendo afuera? Si está en la clase, ¿por qué dejar que otros lo manipulen? (¿Por qué incluso proporcionar const getters)? – nakiya

+0

En su pregunta, lo que debe hacer es pasar un objeto de 'Mechanic' a un objeto' Car' para que el objeto 'Car' pueda pasar su objeto' Engine' al objeto 'Mechanic'. De esta manera, eliminas el getter y un 'Terrorist' no podrá acceder al motor de un' Car'. – nakiya

0

sí, tiene sentido - para facilidad de mantenimiento, validación y coherencia.

puede que tenga que cambiar muchos aspectos de la clase en el futuro, siempre que un acceso puede ayudar a minimizar la rotura del código del cliente.

puede introducir toda la lógica de validación que necesita aquí, para asegurar que el motor es un puntero válido, no está en un estado inutilizable, etc.

finalmente, su código será consistente: no tendrá para abrir el encabezado y conocer la visibilidad del miembro, siempre lo sabrá. esto también es útil con plantillas.

0

En este caso sería más bien necesita una función Car.fix(const Mechanic&) que a su vez le da al motor a la Mechanic, decir: Engine.fix(const Mechanic&), como supongo que se modificará el estado de la Engine.

La idea original de utilizar clases era unir los datos con sus funciones de acceso. Si lo hace setter o getter, que simplemente devuelve una información interna, significa que sus datos no están vinculados con su funcionalidad de acceso: su clase no está completa.

Desea solamente exponer los datos nuevos que una clase emite. Diga Car.get_exhaust() y el Car no tiene el escape, solo lo produce, cuando usted lo pide. ;)

O Fire Riefle.fire() mientras que hay acceso para Riefle::Trigger será fijado por el mecánico de este modo: Trigger.fix_by(Mechanic) y luego el fix_by llamará decir Mechanic.add_working_hour(0.5). XD

Cuestiones relacionadas