Pregunta

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

¿Fue útil?

Solución

¿Debería utilizar alguna vez variables miembro protegidas?

Depende de lo exigente que seas con el estado de ocultación.

  • Si no desea ninguna filtración del estado interno, entonces declarar privadas todas sus variables miembro es el camino a seguir.
  • Si realmente no le importa que las subclases puedan acceder al estado interno, entonces protected es suficiente.

Si aparece un desarrollador y crea subclases en su clase, es posible que la estropee porque no la comprende completamente.Con los miembros privados, aparte de la interfaz pública, no pueden ver los detalles específicos de la implementación de cómo se están haciendo las cosas, lo que le brinda la flexibilidad de cambiarlos más adelante.

Otros consejos

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

No tienen ninguna ventaja particular sobre los métodos/propiedades protegidos (una vez pudieron tener una ligera ventaja de rendimiento), y también se usaron más en una era en la que la herencia muy profunda estaba de moda, lo cual no es así en este momento.

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

Si surge una situación en la que necesito acceso a esa variable o método privado desde una clase derivada, lo cambio de privado a protegido.

Esto rara vez sucede; realmente no soy un fanático de la herencia, ya que no es una forma particularmente buena de modelar la mayoría de las situaciones.En cualquier caso, continúa, no te preocupes.

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

El simple hecho del asunto es, si algún otro desarrollador llega un año después y decide que necesita acceso a su variable miembro privada, simplemente editará el código, lo cambiará a protegido y continuará con su negocio.

Las únicas excepciones reales a esto son si usted está en el negocio de enviar archivos DLL binarios en forma de caja negra a terceros.Esto consiste básicamente en Microsoft, los proveedores de 'Control de cuadrícula de datos personalizado' y tal vez algunas otras aplicaciones grandes que se entregan con bibliotecas de extensibilidad.A menos que esté en esa categoría, no vale la pena gastar tiempo o esfuerzo en preocuparse por este tipo de cosas.

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

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

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

  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.Crear un método de establecimiento protegido para la variable mantiene ese control.

  3. Establezca un punto de interrupción o agregue salida de depuración cuando se lea o escriba la variable.

  4. Cambie el nombre de esa variable miembro sin buscar en todo el código que podría usarla.

En general, creo que sería un caso raro que recomendaría crear una variable miembro protegida.Es mejor dedicar unos minutos a exponer la propiedad a través de captadores/definidores que horas más tarde rastreando un error en algún otro código que modificó la variable protegida.No solo eso, sino que está asegurado contra agregar funcionalidades futuras (como carga diferida) sin romper el código dependiente.Es más difícil hacerlo más tarde que hacerlo ahora.

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

Las variables miembro protegidas tienen desventajas importantes porque permiten efectivamente que el código del cliente (la subclase) acceda al estado interno de la clase base.Esto impide que la clase base mantenga eficazmente sus invariantes.

Por la misma razón, las variables miembro protegidas también hacen que escribir código multiproceso seguro sea significativamente más difícil a menos que se garantice que sea constante o se limite a un solo subproceso.

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

Además, si eres un purista de OO, los objetos colaboran/se comunican enviando mensajes, no leyendo/estableciendo estados.

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

La cuestión clave para mí es que una vez que proteges una variable, no puedes permitir que ningún método de tu clase lo haga. confiar de que su valor esté dentro de un rango, porque una subclase siempre puede colocarlo fuera de rango.

Por ejemplo, si tengo una clase que define el ancho y el alto de un objeto renderizable y protejo esas variables, entonces no puedo hacer suposiciones sobre (por ejemplo) la relación de aspecto.

Críticamente, puedo nunca Haga esas suposiciones en cualquier momento desde el momento en que el código se publica como biblioteca, ya que incluso si actualizo mis configuradores para mantener la relación de aspecto, no tengo garantía de que las variables se establezcan a través de los configuradores o se acceda a ellas a través de los captadores en el código existente.

Ninguna subclase de mi clase tampoco puede optar por hacer esa garantía, ya que tampoco pueden hacer cumplir los valores de las variables. incluso si ese es el objetivo de su subclase.

Como ejemplo:

  • Tengo una clase de rectángulo 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 altos a valores válidos para una visualización gráfica.
  • Pero eso es imposible ahora, desde mi clase DisplayedRectangle no puedo realmente restringe esos valores, ya que cualquier subclase del mismo podría anular los valores directamente, sin dejar de ser tratado como DisplayedRectangle.

Al restringir las variables para que sean privadas, puedo imponer el comportamiento que deseo a través de definidores o captadores.

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

Pero tengo un buen ejemplo:Digamos que puedes algún tipo de contenedor genérico.Tiene una implementación interna y accesores internos.Pero es necesario ofrecer al menos 3 accesos públicos a sus datos:mapa, hash_map, tipo vector.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 Base directamente sería tan complicado que debería estar prohibido.

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

En resumen, sí.

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

Solo para el registro, bajo el ítem 24 de "C ++ excepcional", en una de las notas al pie, Sutter dice "nunca escribiría una clase que tenga una variable de miembro público o protegido.¿bien?(Independientemente del mal ejemplo dado por algunas bibliotecas)".

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

No existen ventajas o desventajas reales para las variables miembro protegidas, es una cuestión de lo que necesita en su situación específica.En general, es una práctica aceptada declarar las variables miembro como privadas y permitir el acceso externo a través de propiedades.Además, algunas herramientas (p. ej.algunos mapeadores O/R) esperan que los datos del objeto estén representados por propiedades y no reconocen variables miembro públicas o protegidas.Pero si sabe que quiere que sus subclases (y SÓLO sus subclases) accedan a una determinada variable, no hay razón para no declararla como protegida.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top