oop protected

oop - ¿Debería alguna vez usar variables de miembro protegidas?



protected (10)

¿Debería alguna vez usar variables de miembro protegidas?

Depende de cuán quisquilloso se trate de ocultar el estado.

  • Si no desea ninguna fuga de estado interno, entonces declarar todas sus variables miembro es el camino a seguir.
  • Si realmente no te importa que las subclases puedan acceder al estado interno, entonces lo protegido es lo suficientemente bueno.

Si aparece un desarrollador y subclasifica a tu clase, pueden estropearlo porque no lo entienden completamente. Con miembros privados, que no sean la interfaz pública, no pueden ver los detalles específicos de implementación de cómo se están haciendo las cosas, lo que le da la flexibilidad de cambiarlo más adelante.

¿Debería alguna vez usar variables de miembro protegidas? ¿Cuáles son las ventajas y qué problemas puede causar esto?


El problema clave para mí es que una vez que hagas que una variable esté protegida, no puedes permitir que ningún método en tu clase confíe en que su valor está dentro de un rango, porque una subclase siempre puede ubicarlo fuera del rango.

Por ejemplo, si tengo una clase que define el ancho y alto de un objeto que se puede hacer una presentación, y hago que esas variables estén protegidas, entonces no puedo hacer suposiciones sobre, por ejemplo, la relación de aspecto.

Críticamente, nunca puedo hacer esas suposiciones en ningún momento desde el momento en que se lanza el código como biblioteca, ya que incluso si actualizo mis setters para mantener la relación de aspecto, no tengo garantía de que las variables se establezcan a través de los setters o se acceda a través del getters en el código existente.

Tampoco puede ninguna subclase de mi clase elegir hacer esa garantía, ya que tampoco pueden imponer los valores de las variables, incluso si ese es el punto completo de su subclase .

Como ejemplo:

  • Tengo una clase rectangular con ancho y alto almacenados como variables protegidas.
  • Una subclase obvia (dentro de mi contexto) es una clase "DisplayedRectangle", donde la única diferencia es que restrinjo los anchos y alturas a valores válidos para una visualización gráfica.
  • Pero eso es imposible ahora , ya que mi clase DisplayedRectangle realmente no puede restringir esos valores, ya que cualquier subclase de ella podría anular los valores directamente, mientras se trata como un rectángulo visualizado.

Al restringir las variables para que sean privadas, puedo aplicar el comportamiento que deseo a través de setters o getters.


El sentimiento general hoy en día es que causan un acoplamiento indebido entre las clases derivadas y sus bases.

No tienen una ventaja particular sobre los métodos / propiedades protegidos (una vez tuvieron una pequeña ventaja de rendimiento) y también se usaron más en una época en la que la herencia profunda estaba de moda, lo que no ocurre en este momento.


En el nivel de diseño, podría ser apropiado usar una propiedad protegida, pero para la implementación no veo ninguna ventaja en mapear esto a una variable miembro protegida en lugar de métodos de acceso / mutador.

Las variables de miembro protegido tienen desventajas significativas porque permiten efectivamente el acceso de código de cliente (la subclase) al estado interno de la clase de clase base. Esto evita que la clase base mantenga efectivamente sus invariantes.

Por la misma razón, las variables de miembros protegidas también hacen que la escritura segura de código multiproceso sea significativamente más difícil a menos que se garantice constante o confinada a un solo hilo.

Los métodos de acceso / mutador ofrecen considerablemente más estabilidad de API y flexibilidad de implementación en mantenimiento.

Además, si eres un purista OO, los objetos colaboran / se comunican enviando mensajes, no leyendo / configurando el estado.

A cambio, ofrecen muy pocas ventajas. No necesariamente los eliminaría del código de otra persona, pero no los uso yo mismo.


En general, mantendría sus variables miembro protegidas en el raro caso en el que tenga control total sobre el código que las usa también. Si está creando una API pública, yo diría que nunca. A continuación, nos referiremos a la variable miembro como una "propiedad" del objeto.

Esto es lo que su superclase no puede hacer después de hacer que una variable miembro esté protegida en lugar de privada con accesores:

  1. crea perezosamente un valor sobre la marcha cuando se lee la propiedad. Si agrega un método getter protegido, puede crear el valor de forma lenta y reenviarlo.

  2. saber cuándo la propiedad ha sido modificada o eliminada. Esto puede introducir errores cuando la superclase hace suposiciones sobre el estado de esa variable. Hacer un método setter protegido para la variable mantiene ese control.

  3. Establezca un punto de interrupción o agregue resultados de depuración cuando la variable sea leída o escrita.

  4. Cambie el nombre de esa variable miembro sin buscar todo el código que pueda usarla.

En general, creo que sería el caso raro que recomendaría hacer una variable miembro protegida. Es mejor pasar unos minutos exponiendo la propiedad a través de getters / setters que horas después rastreando un error en algún otro código que modificó la variable protegida. No solo eso, sino que está asegurado de no agregar funcionalidad futura (como la carga diferida) sin romper el código dependiente. Es más difícil hacerlo más tarde que hacerlo ahora.


En resumen, sí.

Las variables de miembro protegidas permiten el acceso a la variable desde cualquier subclase, así como cualquier clase en el mismo paquete. Esto puede ser muy útil, especialmente para datos de solo lectura. Sin embargo, no creo que sean necesarios, ya que cualquier uso de una variable miembro protegida se puede replicar utilizando una variable miembro privada y un par de getters y setters.


Generalmente, si algo no se concibe deliberadamente como público, lo hago privado.

Si surge una situación en la que necesito acceder a esa variable o método privado de una clase derivada, la cambio de privada a protegida.

Esto casi nunca ocurre. Realmente no soy partidario de la herencia, ya que no es una buena manera de modelar la mayoría de las situaciones. En cualquier caso, continúe, sin preocupaciones.

Diría que esto está bien (y probablemente sea la mejor manera de hacerlo) para la mayoría de los desarrolladores.

El simple hecho del asunto es que si algún otro desarrollador aparece un año después y decide que necesitan acceder a su variable miembro privada, simplemente van a editar el código, cambiarlo a protegido y continuar con su negocio.

Las únicas excepciones reales a esto son si está en el negocio de enviar dll binarios en forma de caja negra a terceros. Básicamente se trata de Microsoft, los proveedores de ''Custom DataGrid Control'' y, tal vez, algunas otras aplicaciones grandes que incluyen bibliotecas de extensibilidad. A menos que esté en esa categoría, no vale la pena gastar el tiempo / esfuerzo para preocuparse por este tipo de cosas.


La mayoría de las veces, es peligroso usar protegido porque rompe un poco la encapsulación de su clase, lo que podría ser desglosado por una clase derivada mal diseñada.

Pero tengo un buen ejemplo: digamos que puedes tener algún tipo de contenedor genérico. Tiene una implementación interna y acceso interno. Pero debe ofrecer al menos 3 accesos públicos a sus datos: map, hash_map, vector-like. Entonces tienes algo como:

template <typename T, typename TContainer> class Base { // etc. protected TContainer container ; } template <typename Key, typename T> class DerivedMap : public Base<T, std::map<Key, T> > { /* etc. */ } template <typename Key, typename T> class DerivedHashMap : public Base<T, std::hash_map<Key, T> > { /* etc. */ } template <typename T> class DerivedVector : public Base<T, std::vector<T> > { /* etc. */ }

Utilicé este tipo de código hace menos de un mes (por lo que el código es de memoria). Después de pensar un poco, creo que, si bien el contenedor Base genérico debería ser una clase abstracta, incluso si puede vivir bastante bien, porque usar directamente la Base sería un gran dolor, debería estar prohibido.

Resumen Por lo tanto, tiene datos protegidos utilizados por la clase derivada. Aún así, debemos tomar en cuenta el hecho de que la clase Base debe ser abstracta.


Para obtener información detallada sobre los modificadores de acceso .Net, vaya aquí

No existen ventajas o desventajas reales para las variables de miembro protegidas, es una cuestión de lo que necesita en su situación específica. En general, se acepta la práctica de declarar las variables miembro como privadas y habilitar el acceso externo a través de las propiedades. Además, algunas herramientas (por ejemplo, algunos mapeadores O / R) esperan que los datos de los objetos sean representados por propiedades y no reconocen las variables públicas o protegidas de los miembros. Pero si sabe que quiere que sus subclases (y SOLO sus subclases) accedan a cierta variable, no hay razón para no declararla como protegida.


Solo para el registro, en el artículo 24 de "Exceptional C ++", en una de las notas a pie de página, Sutter dice "nunca escribirías una clase que tenga una variable miembro pública o protegida. ¿Cierto? (Independientemente del pobre ejemplo establecido por algunas bibliotecas) .) "