¿Por qué necesitamos variables privadas?

202

¿Por qué necesitamos variables privadas en las clases?

Todos los libros sobre programación que he leído dicen que esta es una variable privada, así es como se define, pero se detiene allí.

La redacción de estas explicaciones siempre me pareció que realmente tenemos una crisis de confianza en nuestra profesión. Las explicaciones siempre sonaban como si otros programadores desordenaran nuestro código. Sin embargo, hay muchos lenguajes de programación que no tienen variables privadas.

  1. ¿Qué ayudan las variables privadas a prevenir?

  2. ¿Cómo decide si una propiedad en particular debe ser privada o ¿no? Si, por defecto, todos los campos DEBERÍAN ser privados, entonces ¿por qué hay miembros de datos públicos en una clase?

  3. ¿En qué circunstancias debería publicarse una variable?

pregunta mwallace 10.04.2012 - 07:31

14 respuestas

295

No es tanto una cuestión de confianza, sino una cuestión de gestión de la complejidad.

Se puede acceder a un miembro público desde fuera de la clase, que por consideraciones prácticas significa "potencialmente en cualquier lugar". Si algo sale mal en un campo público, el culpable puede estar en cualquier parte, y por lo tanto, para rastrear el error, es posible que tenga que mirar un montón de código.

Por el contrario, solo se puede acceder a un miembro privado desde dentro de la misma clase, por lo que si algo va mal con eso, generalmente solo hay un archivo de origen para ver. Si tiene un millón de líneas de código en su proyecto, pero sus clases se mantienen pequeñas, esto puede reducir su esfuerzo de seguimiento de errores en un factor de 1000.

Otra ventaja está relacionada con el concepto de "acoplamiento". Un miembro público m de una clase A que es usado por otra clase B introduce una dependencia: si cambia m en A , también debe verificar los usos de m en B . Peor aún, nada en la clase A le dice dónde se está utilizando m , por lo que nuevamente debe buscar en todo el código base; Si está escribiendo una biblioteca, incluso debe asegurarse de que el código que está fuera de su proyecto no se rompa debido a su cambio. En la práctica, las bibliotecas tienden a mantener las firmas de sus métodos originales el mayor tiempo posible, sin importar qué tan dolorosas sean, y luego introducen un bloque de cambios de última hora con una actualización de la versión principal. Con los miembros privados, por el contrario, puede excluir las dependencias de inmediato, no se puede acceder a ellas desde fuera, por lo que todas las dependencias están contenidas dentro de la clase.

En este contexto, "otros programadores" incluyen tu futuro y tu pasado. Lo más probable es que sepa ahora que no debería hacer esto X con su variable Y, pero está obligado a haber olvidado tres meses después cuando un cliente lo necesita con urgencia para implementar alguna función. y te preguntas por qué hacer X rompe Y de formas oscuras.

Entonces, en cuanto a cuándo deberías hacer las cosas privadas: yo diría que todo sea privado por defecto, y luego expondré solo aquellas partes que absolutamente tienen que ser públicas. Cuanto más puedas hacer en privado, mejor.

    
respondido por el tdammers 10.04.2012 - 07:48
110

Las variables privadas ayudan a evitar que las personas dependan de ciertas partes de su código. Por ejemplo, digamos que desea implementar alguna estructura de datos. Desea que los usuarios de su estructura de datos no se preocupen por cómo que lo implementó, sino que simplemente usan la implementación a través de su interfaz bien definida. La razón es que si nadie depende de su implementación, puede cambiarla cuando lo desee. Por ejemplo, puede cambiar la implementación de back-end para mejorar el rendimiento. Cualquier otro desarrollador que dependa de sus implementaciones se romperá, mientras que los usuarios de la interfaz estarán bien. Tener la flexibilidad para cambiar implementaciones sin afectar a los usuarios de la clase es un gran beneficio que el uso de variables privadas (y más ampliamente, encapsulación ) te da.

Además, no es realmente una "crisis de confianza". Si hace pública una pieza de datos, no puede asegurarse de que nadie dependa de ella. A menudo es muy conveniente depender de alguna variable específica de la implementación, en lugar de pasar por la interfaz pública, especialmente en el momento límite. Además, los desarrolladores no siempre se darán cuenta de que dependen de algo que podría cambiar.

Así que este tipo de respuestas a sus otras preguntas, espero. Todos los detalles de su implementación deben ser privados, y la parte pública debe ser una interfaz pequeña, concisa y bien definida para usar su clase.

    
respondido por el Oleksi 10.04.2012 - 07:41
24

La palabra clave aquí es Encapsulation . En OOP, desea utilizar variables privadas para imponer la encapsulación adecuada de sus objetos / clases.

Mientras que otros programadores no están tratando de atraparlo, sí interactúan con su código. Si no hace que una variable sea privada, es posible que se refieran a ella en su propio código sin querer hacer ningún daño. Sin embargo, si necesita volver a su clase y cambiar algo, ya no sabe quién usa qué variable y dónde. El objetivo de la encapsulación es hacer que la interfaz externa de la clase sea explícita para que sepa que solo otros métodos (típicamente) podrían haber sido utilizados por otros.

  1. Por lo tanto, las variables privadas aseguran que la variable correspondiente permanezca solo en la clase definitoria. Si necesita cambiarlo, el cambio es local a la clase en sí.

  2. En los lenguajes tradicionales como C ++ o Java, usualmente haces que todo sea privado y solo accesible por parte de los getters y setters correspondientes. No hay necesidad de decidir mucho realmente.

  3. A veces, f.ex. en una estructura C ++, necesitas una clase solo como una forma de agrupar varias cosas. Por ejemplo, considere una clase Vector que tiene solo un atributo x y y . En esos casos, puede permitir el acceso directo a estos atributos al declararlos públicos. En particular, no debe preocuparse si algún código externo modifica un objeto de su clase escribiendo directamente nuevos valores en x o y .

Como punto adicional, observe que este asunto se considera ligeramente diferente en otros idiomas. Por ejemplo, los lenguajes que están fuertemente arraigados en la programación funcional enfatizan la inmutabilidad de los datos, es decir, los valores de los datos no se pueden cambiar en absoluto. En tales casos, no tiene que preocuparse por lo que otros programadores (o más bien su código) hacen con sus datos. Simplemente no pueden hacer nada que pueda afectar su código, porque todos los datos son inmutables.

En esos idiomas, por lo tanto, obtienes algo llamado principio de acceso uniforme , en el que uno no distingue deliberadamente métodos como captadores y configuradores, pero proporciona acceso directo a la variable / función. Por lo tanto, puede decir que las declaraciones privadas son mucho más populares en los escenarios orientados a objetos.

Esto también muestra cómo ampliar su conocimiento para incluir otros campos hace que vea conceptos existentes de una manera completamente nueva.

    
respondido por el Frank 10.04.2012 - 07:48
6

Las variables privadas aseguran que las referencias posteriores fuera del alcance de un objeto o función no afecten inadvertidamente a otras variables. Para grandes proyectos de programación, esto puede ayudar a evitar muchos problemas interesantes (que normalmente no son detectados por el compilador).

Por ejemplo, los lenguajes prototípicos como Javascript pueden permitir a los usuarios utilizar las variables como mejor les parezcan:

function SomeObject() {
    this.a = 2; //Public (well, actually protected) variable

    this.showA = function() {
        alert(this.a);
    }
}

//Some lines down...

var obj = new SomeObject();
obj.a = 3;
obj.showA(); //Will alert 3. Uh oh!

Si esa variable fuera privada, no se podría cambiar desde el exterior:

function SomeObject() {
    var a = 2; //Private variable

    this.showA = function() {
        alert(a);
    }
}

//Some lines down...

var obj = new SomeObject();
obj.a = 3;
obj.showA(); //Will alert 2

Dicho esto, no todas las variables deben ser privadas y el uso excesivo de las variables privadas puede hacer que el código sea más engorroso. Los campos triviales que no afectan seriamente a un objeto no necesitan los métodos get() y set() .

Las variables privadas también hacen que sea más fácil expandir el código en el futuro, sin depender de la documentación pesada en cuanto a lo que hacen las muchas variables públicas. Existe una amenaza menor de romper accidentalmente la funcionalidad si se pueden sobrescribir menos variables.

Las variables públicas deben usarse cuando un objeto / función accederá a otros objetos / funciones, ya que, como regla, las variables privadas no pueden hacer esto. Puede tener desde unas pocas hasta bastantes variables públicas, y no es malo usarlas si se usan correctamente.

    
respondido por el Jeffrey Sweeney 10.04.2012 - 07:52
6

Hay algunas buenas respuestas que citan los beneficios para los futuros mantenedores y usuarios de una clase. Sin embargo, también hay beneficios para el diseño original. Proporciona un punto de demarcación claro entre cuándo su objetivo es hacer las cosas más fáciles para usted y cuándo su objetivo es facilitar las cosas para el usuario de la clase. Cuando eliges entre público y privado, le indica al cerebro que cambie a un modo u otro, y obtienes una API mejor.

No es que los idiomas sin privacidad hagan que ese diseño sea imposible, pero menos probable. En lugar de que se le pida que escriba algo como foo.getBar() , las personas tienden a pensar que un captador no es necesario, porque es más fácil escribir foo.bar , pero esa decisión no se vuelve a consultar cuando más tarde termina con monstruosidades más largas como %código%. Los programadores que nunca han trabajado en un lenguaje más estricto ni siquiera pueden ver qué hay de malo en eso.

Es por eso que en los idiomas sin privacidad las personas a menudo adoptan estándares de nomenclatura que lo simulan, como añadir un guión bajo a todos los miembros "privados". Es una señal útil incluso cuando el idioma no lo impone.

    
respondido por el Karl Bielefeldt 10.04.2012 - 17:53
3

Todas las variables deben ser privadas a menos que sean absolutamente públicas (lo cual es casi nunca, debes usar propiedades / captadores y definidores).

Las variables proporcionan en gran medida el estado del objeto, y las variables privadas evitan que otros entren y cambien el estado del objeto.

    
respondido por el bbb 10.04.2012 - 07:38
2
  • ¿Qué ayudan a prevenir las variables privadas?

Se trata de dejar en claro qué propiedades y métodos son la interfaz y cuáles son realmente la funcionalidad principal. Los métodos / propiedades públicas se refieren a otro código, a menudo al código de otros desarrolladores que utilizan sus objetos. Nunca he trabajado en equipos de más de 100 en el mismo proyecto, pero en mi experiencia de quizás equipos de 3-5 con hasta 20 desarrolladores más que usan cosas que he escrito, las otras preocupaciones parecen tontas.

Nota: Soy principalmente un desarrollador de JavaScript. Por lo general, no me preocupa que otros desarrolladores vean mi código, y me doy cuenta de que simplemente pueden redefinir mis cosas en cualquier momento. Supongo que son lo suficientemente competentes como para saber qué están haciendo primero. De lo contrario, es poco probable que esté trabajando en un equipo que no use el control de código fuente.

  • ¿Cómo decide si un conjunto particular de propiedades debe ser privado o no? Si, de forma predeterminada, todos los campos DEBERÍAN ser privados, ¿por qué hay miembros de datos públicos en una clase?

Solía pensar que era una tontería poner captadores y definidores en propiedades privadas cuando en realidad no estaba realizando ningún tipo de validación u otro tratamiento especial de la propiedad que se establecería. Todavía no creo que sea siempre necesario, pero cuando se trata de una gran escala, una gran complejidad, pero lo más importante es que muchos otros desarrolladores que confían en que sus objetos se comportan de manera consistente, puede ser útil hacer las cosas de una manera Manera consistente y uniforme. Cuando las personas ven métodos llamados getThat y setThat , saben exactamente cuáles son sus intenciones y pueden escribir sus objetos para interactuar con los suyos con la expectativa de que siempre obtendrán tomates en lugar de tomahtos. Si no lo hacen, saben que su objeto les está dando algo que probablemente no debería, lo que significa que está permitiendo que otro objeto haga algo con los datos que probablemente no debería. Puedes controlar eso a medida que surja la necesidad.

La otra gran ventaja es que es más fácil que sus objetos se entreguen o interpreten los valores de manera diferente a un captador o definidor en función de algún tipo de contexto de estado variable. Debido a que están accediendo a tus cosas con un método, es mucho más fácil cambiar la forma en que opera tu objeto más adelante sin romper otro código que depende de él. El principio importante es que solo su objeto realmente cambia los datos de los que se ha hecho responsable. Esto es particularmente importante para mantener su código acoplado libremente, lo que es una gran victoria en términos de portabilidad y facilidad de modificación.

  • ¿Bajo qué circunstancias debería hacerse pública una variable?

Con las funciones de primera clase (puede pasar funciones como argumentos), no puedo pensar en muchas otras buenas razones, además de que no es muy necesario hacerlo en proyectos de menor escala. Sin él, supongo que podría tener miembros que sean procesados en gran medida y con regularidad por otros objetos en la medida en que parece un poco engorroso llamar constantemente a get y sets en un objeto que realmente no toca esos datos, pero que en en sí mismo me haría preguntarme por qué el objeto era responsable de esos datos. En términos generales, tiendo a querer reexaminar mi arquitectura en busca de fallas antes de decidir si una propiedad de datos públicos es necesaria. En mi opinión, no hay nada de malo en que un lenguaje te permita hacer algo que suele ser una mala idea. Algunos idiomas no están de acuerdo.

    
respondido por el Erik Reppen 10.04.2012 - 18:47
2

Consulte esta publicación mía a una pregunta relacionada sobre SO .

En resumen, el alcance variable le permite mostrar a los consumidores de su código lo que deberían y no deberían estar jugando. Una variable privada puede contener datos que han sido "examinados" mediante el uso de un establecedor de propiedades o un método de procesamiento para garantizar que todo el objeto se encuentre en un estado coherente. Cambiar el valor de la variable privada directamente puede hacer que el objeto se vuelva inconsistente. Al hacerlo privado, alguien tiene que trabajar muy duro y tener permisos de tiempo de ejecución realmente altos para cambiarlo.

Por lo tanto, el alcance del miembro adecuado es clave en el código de auto-documentación.

    
respondido por el KeithS 10.04.2012 - 16:42
2

No tiene nada que ver con la confianza o el miedo a los ataques, se trata únicamente de encapsulación, no de forzar información innecesaria sobre el usuario de la clase.

Considere las constantes privadas: no deben contener valores secretos (deben almacenarse en otro lugar), no se pueden cambiar, no es necesario que se pasen a su clase (de lo contrario, tendrían que ser públicos). El único uso posible para ellos es como constantes en OTRAS clases. Pero si haces eso, esas clases ahora dependen de tu clase, para hacer un trabajo que no esté relacionado con tu clase. Si cambia la constante, otras clases podrían romperse. Eso es malo desde ambos lados: como el escritor de tu clase, quieres la libertad de cambiar tanto como sea posible y no quieres preocuparte por cosas que están fuera de tu control. Un consumidor de su clase quiere poder depender de los detalles expuestos de su clase, sin preocuparse de que lo cambie y rompa su código.

Un consumidor de su clase quiere saber todo lo necesario para INTERACTUAR con su clase, y no quiere saber nada sobre su clase que no cambie la forma en que lo hacen: es una trivia inútil. Si ha usado un lenguaje con reflexión, ¿con qué frecuencia lo ha usado para aprender no cómo una clase hace algo o dónde está lanzando una excepción inesperadamente, sino simplemente el nombre de los campos y métodos privados? Apuesto a que nunca. Porque no tienes uso para ese conocimiento.

    
respondido por el jmoreno 10.04.2012 - 17:41
1

Voy a hablar sobre el valor de la encapsulación desde una perspectiva diferente usando un ejemplo real. Hace bastante tiempo (a principios de los 80) se escribió un juego para Radio Shack Color Computer llamado Dungeons of Daggorath. Hace algunos años, Richard Hunerlach lo portó de una lista de ensambladores de papel a C / C ++ ( enlace ). Algún tiempo después, obtuve el código y comencé a reformularlo para obtener una mejor encapsulación ( enlace ).

El código ya estaba factorizado en diferentes objetos para manejar la programación, el video, la entrada del usuario, la creación de mazmorras, monstruos, etc., pero definitivamente se podría decir que fue portado desde el ensamblador. Mi mayor tarea fue aumentar la encapsulación. Con eso me refiero a obtener diferentes partes del código para que sus narices se salgan del asunto del otro. Hubo muchos lugares, por ejemplo, que cambiarían las variables de video directamente para tener algún efecto. Algunos lo hicieron con la comprobación de errores, otros no, otros tenían ideas sutilmente diferentes de lo que significaba cambiar esa cosa. Había mucha duplicación de código. En cambio, la sección de video necesitaba tener una interfaz para realizar las tareas deseadas, y el código para hacerlo podría ser todo en un solo lugar, una idea, un lugar para depurar. Ese tipo de cosas estaba desenfrenada. Todos los objetos accedieron directamente a todos los demás objetos y el código se duplicó en todas partes.

Cuando el código comenzó a separarse, los errores que ni siquiera habían sido diagnosticados desaparecieron. El código se convirtió en mayor calidad. Cada tarea se convirtió en la responsabilidad de un lugar en el código y solo había un lugar para hacerlo bien. (Todavía encuentro más cada vez que hago otra pasada a través del código).

Todo lo que es visible acerca de su código es su interfaz. Si quieres que sea o no. Si limita la visibilidad lo más posible, no tendrá la tentación de poner el código en el lugar equivocado más tarde. Hace obvio qué parte del código es responsable de qué datos. Hace un diseño mejor, más limpio, más simple y más elegante.

Si hace que un objeto sea responsable de sus propios datos y proporcione interfaces a todos los demás que necesitan que algo suceda, su código se vuelve MUCHO más sencillo. Simplemente se cae. Tienes pequeñas rutinas simples que hacen una sola cosa. Menos complejidad == menos errores.

    
respondido por el Patrick 17.04.2012 - 21:27
1

Como han dicho otros, las variables privadas son buenas para evitar los usos erróneos que llevan al objeto a un estado incoherente y es difícil rastrear errores y excepciones imprevistas.

Pero, por otro lado, lo que más han ignorado los demás es sobre los campos protegidos.

Una subclase extendida tendrá acceso completo a los campos protegidos, haciendo que el objeto sea tan frágil como si esos campos fueran públicos, pero esa fragilidad se limita a la propia clase que se extiende (a menos que exponga dichos campos aún más).

Por lo tanto, los campos públicos son difíciles de considerar buenos, y hasta la fecha, la única razón para usarlos es para las clases utilizadas como parámetro de configuración (una clase muy simple con muchos campos y sin lógica, por lo que la clase se pasa como un parámetro solo a algún método).

Pero, por otro lado, los campos privados reducen la flexibilidad de su código para otros usuarios.

Flexibilidad frente a problemas, ventajas y desventajas:

Los objetos instanciados por su código en la clase de vainilla con campos protegidos son seguros y son de su exclusiva responsabilidad.

Por otra parte, los objetos que extienden su clase con campos protegidos, creados por los usuarios de su código, son de su responsabilidad, no de usted.

Por lo tanto, los campos / métodos protegidos no están bien documentados, o si los usuarios no entienden realmente cómo se deben usar dichos campos y métodos, tienen una buena posibilidad de causar problemas innecesarios para ellos mismos y para usted.

Por otro lado, hacer que la mayoría de las cosas sean privadas disminuirá la flexibilidad de los usuarios, e incluso puede dejarlos de lado en busca de alternativas mantenidas, ya que tal vez no quieran crear y mantener una bifurcación para que las cosas sucedan a su manera. p>

Entonces, lo que realmente importa es un buen equilibrio entre privado, protegido y público.

Ahora, decidir entre lo privado y lo protegido es el problema real.

¿Cuándo usar protegido?

Cada vez que entienda que un campo puede ser muy flexible, debe codificarse como protegido. Esa flexibilidad es: desde que se convierte en nulo (donde nulo siempre se marca y reconoce como un estado válido que no produce excepciones), hasta que tiene restricciones antes de que sea utilizado por su clase ex. > = 0, < 100, etc., y se corrigen automáticamente para los valores de flujo excesivo / insuficiente, lanzando como máximo un mensaje de advertencia.

Entonces, para un campo tan protegido, puede crear un captador y solo usarlo (en lugar de usar directamente la variable de campo), mientras que otros usuarios no lo pueden usar, en caso de que quieran más flexibilidad para su código específico, en mi ejemplo podría ser como: si quieren que los valores negativos funcionen bien en su clase extendida.

    
respondido por el Aquarius Power 17.06.2016 - 04:48
1

El concepto OOP tiene herencia tiene una de sus características (Java o C ++). Entonces, si vamos a heredar (lo que significa que vamos a acceder a las variables de la clase heredada), existe la posibilidad de afectar esas variables. Así que tenemos que decidir si las variables se pueden cambiar o no.

Solo para este propósito, estamos usando modificadores de acceso en OOP. Uno de los modificadores es privado, lo que significa que solo esa clase puede acceder a él. Cualquier otra clase no puede afectar esas variables.

Como sabemos, protegido significa que la clase que va a heredar puede acceder a él.

Por qué hay un concepto modificador en la POO, se debe a estas razones (cualquier clase puede acceder a otras variables de clase usando el concepto POO). Si no hay un concepto modificador, significa que habría sido difícil al heredar clases o al usar otros conceptos OOP.

    
respondido por el rajNaveen 10.04.2012 - 07:52
0

imo @tdammers no está bien y en realidad es engañoso.

Existen variables privadas para ocultar los detalles de la implementación. Es posible que su clase A esté utilizando un array para almacenar puntuaciones. Mañana es posible que desee utilizar un tree o priority queue en su lugar. Todos los usuarios de tu clase necesitan una forma de ingresar puntajes y nombres addScore() y una forma de averiguar quiénes son los 10 getTop(n) más importantes.

No necesitan acceder a la estructura de datos subyacente. ¿Suena genial? Bueno, hay algunas advertencias.

De todos modos, no deberías almacenar mucho estado, la mayoría no es necesario. El estado de almacenamiento complicará su código incluso cuando está "segregado" a una clase específica. Piénselo, esa variable privada probablemente cambió porque otro objeto se llama método de esa clase. Aún debe averiguar cuándo y dónde se llamó a ese método, y ese método público puede llamarse en cualquier lugar teóricamente.

Lo mejor que puedes hacer es limitar la cantidad de estado que contiene tu programa y usar funciones puras cuando sea posible.

    
respondido por el wolfdawn 03.05.2017 - 20:05
-4

Primero debes entender el concepto de programación orientada a objetos. Tiene abstracción, encapsulación, etc.

Abstracción: se obtiene la idea de la lógica sin necesidad de saber subrayar los detalles de la implementación.

Encapsulación: no puede ver la implementación subrayada del objeto. Solo usted puede ver la interfaz pública del objeto.

Ahora, en una implementación específica con un programa orientado a objetos como C #, Java, C ++, puede implementar estos conceptos.

privado: la implementación que debe ocultarse del mundo exterior. Para que puedas cambiar eso y el usuario de tu clase no se vea afectado.

público: esta es la interfaz mediante la cual uno puede usar su objeto.

    
respondido por el DeveloperArnab 27.06.2013 - 15:08

Lea otras preguntas en las etiquetas