He estado buscando y sé la diferencia teórica.
- public : cualquier clase / función puede acceder al método / propiedad.
- protegido : solo esta clase y cualquier subclase pueden acceder al método / propiedad.
- privado : solo esta clase puede acceder al método / propiedad. Ni siquiera será heredado.
Eso está bien y bueno, la pregunta es, ¿cuál es la diferencia práctica entre ellos? ¿Cuándo usarías private
y cuándo usarías protected
? ¿Existe una buena práctica estándar o aceptable sobre esta?
Hasta ahora, para retener el concepto de herencia y polimorfismo, lo uso public
para cualquier cosa a la que se deba acceder desde el exterior (como constructores y funcionalidad de clase principal), y protected
para métodos internos (lógica, métodos auxiliares, etc.). ¿Estoy en el camino correcto?
(Tenga en cuenta que esta pregunta es para mí, pero también para referencia futura ya que no he visto una pregunta como esta SO).
oop
language-agnostic
coding-style
El fantasma de Madara
fuente
fuente
internal
en lenguaje C # que restringe el nivel de acceso de una clase o sus miembros dentro de un ensamblaje físico. Sin embargo, no estoy seguro de su soporte o algo similar en otros idiomas.Respuestas:
No, no estás en el camino correcto. Una buena regla general es: hacer que todo sea lo más privado posible. Esto hace que su clase esté más encapsulada y permite cambiar las partes internas de la clase sin afectar el código que usa su clase.
Si diseña su clase para que sea heredable, elija cuidadosamente lo que puede ser anulado y accesible desde las subclases, y haga que esté protegido (y finalmente, hablando de Java, si desea hacerlo accesible pero no anulable). Pero tenga en cuenta que, tan pronto como acepte tener subclases de su clase, y haya un campo o método protegido, este campo o método es parte de la API pública de la clase, y no se puede cambiar más adelante sin romper las subclases.
Una clase que no está destinada a ser heredada debe hacerse final (en Java). Puede relajar algunas reglas de acceso (privado a protegido, final a no final) en aras de las pruebas unitarias, pero luego documentarlo y dejar en claro que, aunque el método está protegido, no se debe anular.
fuente
private
vs ¿protected
Cuándo quiero que se herede una propiedad y cuándo no? Realmente no puedo decir si un usuario a veces en el futuro quiere tomar mi clase y extenderla ...Permítanme comenzar esto diciendo que estoy hablando principalmente sobre el acceso a métodos aquí, y en menor medida, marcando las clases como final, no como acceso de miembros.
La vieja sabiduria
tenía sentido en los días en que se escribió, antes de que el código abierto dominara el espacio de la biblioteca del desarrollador y la gestión de VCS / dependencia. se convirtió en hiper colaborativo gracias a Github, Maven, etc. En aquel entonces también se podía ganar dinero restringiendo las formas en que se podía utilizar una biblioteca. Probablemente pasé los primeros 8 o 9 años de mi carrera siguiendo estrictamente esta "mejor práctica".
Hoy, creo que es un mal consejo. A veces hay un argumento razonable para marcar un método privado o una clase final, pero es extremadamente raro, e incluso entonces probablemente no esté mejorando nada.
Alguna vez has:
Estas son las tres racionalizaciones más importantes que he escuchado para marcar métodos privados por defecto:
Racionalización # 1: no es seguro y no hay razón para anular un método específico
No puedo contar la cantidad de veces que me he equivocado acerca de si alguna vez será necesario anular un método específico que he escrito. Después de haber trabajado en varias librerías de código abierto populares, aprendí por las malas el costo real de marcar las cosas como privadas. A menudo elimina la única solución práctica para problemas imprevistos o casos de uso. Por el contrario, nunca en más de 16 años de desarrollo profesional me arrepiento de haber marcado un método protegido en lugar de privado por razones relacionadas con la seguridad API. Cuando un desarrollador elige extender una clase y anular un método, conscientemente dice "Sé lo que estoy haciendo". y por el bien de la productividad, eso debería ser suficiente. período. Si es peligroso, anótelo en la clase / método Javadocs, no solo cierre la puerta a ciegas.
Los métodos de marcado protegidos por defecto son una mitigación para uno de los principales problemas en el desarrollo moderno de SW: falta de imaginación.
Racionalización # 2: mantiene limpias las API públicas / Javadocs
Este es más razonable y, dependiendo del público objetivo, incluso podría ser lo correcto, pero vale la pena considerar cuál es el costo de mantener la API "limpia": la extensibilidad. Por las razones mencionadas anteriormente, probablemente tenga más sentido marcar cosas protegidas por defecto por si acaso.
Racionalización # 3: mi software es comercial y necesito restringir su uso.
Esto también es razonable, pero como consumidor iría con el competidor menos restrictivo (suponiendo que no existan diferencias de calidad significativas) cada vez.
Nunca digas nunca
No digo que nunca marques los métodos como privados. Estoy diciendo que la mejor regla general es "proteger los métodos a menos que haya una buena razón para no hacerlo".
Este consejo es el más adecuado para quienes trabajan en bibliotecas o proyectos de mayor escala que se han dividido en módulos. Para proyectos más pequeños o más monolíticos, no tiende a importar tanto ya que usted controla todo el código de todos modos y es fácil cambiar el nivel de acceso de su código si lo necesita. Aun así, todavía daría el mismo consejo :-)
fuente
Rationalization # 1
: cuando marco algo como protegido, elijo hacerlo explícitamente, ya que siento que este comportamiento no es definitivo y podría ser un caso en el que las clases de mi hijo querrían anularlo. Si no estoy tan seguro, me gustaría hacerlo privado por defecto. Especialmente en un lenguaje como C # que mantiene un método no virtual de forma predeterminada, agregar solo un especificador de acceso protegido no tiene sentido. Debe agregar ambosvirtual
yprotected
palabras clave para que su intención sea muy clara. Además, las personas prefieren la asociación a la herencia, por loprotected
que, por defecto, es difícil de percibir¡Deja de abusar de los campos privados!
Los comentarios aquí parecen apoyar abrumadoramente el uso de campos privados. Bueno, entonces tengo algo diferente que decir.
¿Son buenos los campos privados en principio? Si. ¡Pero decir que una regla de oro es hacer que todo sea privado cuando no estés seguro de que definitivamente está mal ! No verá el problema hasta que se encuentre con uno. En mi opinión, debe marcar los campos como protegidos si no está seguro .
Hay dos casos en los que desea extender una clase:
No hay nada malo con los campos privados en el primer caso. El hecho de que las personas abusen de los campos privados lo hace muy frustrante cuando descubres que no puedes modificar la mierda.
Considere una biblioteca simple que modela automóviles:
El autor de la biblioteca pensó: no hay razón para que los usuarios de mi biblioteca necesiten acceder a los detalles de implementación de la
assembleCar()
derecha. Marquemos el tornillo como privado.Bueno, el autor está equivocado. Si desea modificar solo el
assembleCar()
método sin copiar toda la clase en su paquete, no tiene suerte. Tienes que reescribir tu propioscrew
campo. Digamos que este automóvil usa una docena de tornillos, y cada uno de ellos involucra un código de inicialización no trivial en diferentes métodos privados, y todos estos tornillos están marcados como privados. En este punto, comienza a apestar.Sí, puede discutir conmigo que el autor de la biblioteca podría haber escrito un código mejor para que no haya nada malo en los campos privados . No estoy argumentando que el campo privado es un problema con OOP . Es un problema cuando las personas los usan.
La moraleja de la historia es que, si está escribiendo una biblioteca, nunca sabe si sus usuarios desean acceder a un campo en particular. Si no está seguro, márquelo
protected
para que todos estén más felices más tarde. Al menos no abuses del campo privado .Apoyo mucho la respuesta de Nick.
fuente
Hace un tiempo leí un artículo que hablaba sobre bloquear todas las clases tanto como sea posible. Haga que todo sea final y privado a menos que tenga una necesidad inmediata de exponer algunos datos o funcionalidades al mundo exterior. Siempre es fácil ampliar el alcance para ser más permisible más adelante, pero no al revés. Consideremos en primer lugar hacer tantas cosas como sea posible
final
lo que hará que la elección entreprivate
yprotected
mucho más fácil.Ahora, si te queda una clase final, haz que todo sea privado a menos que el mundo necesite absolutamente algo: hazlo público.
Si te queda una clase que tiene subclase (s), entonces examina cuidadosamente cada propiedad y método. Primero considere si incluso desea exponer esa propiedad / método a subclases. Si lo hace, considere si una subclase puede causar estragos en su objeto si arruina el valor de la propiedad o la implementación del método en el proceso de anulación. Si es posible, y desea proteger la propiedad / método de su clase incluso de subclases (suena irónico, lo sé), entonces hágalo privado. De lo contrario, protégelo.
Descargo de responsabilidad: no programo mucho en Java :)
fuente
final class
en Java es una clase de la que no se puede heredar. Afinal method
no es virtual, es decir, no puede ser reemplazado por una subclase (los métodos Java son virtuales por defecto). Afinal field/parameter/variable
es una referencia de variable inmutable (en el sentido de que no se puede modificar después de que se inicializó).¿Cuándo usarías
private
y cuándo usaríasprotected
?La herencia privada puede considerarse implementada en términos de relación en lugar de una relación IS-A . En pocas palabras, la interfaz externa de la clase heredada no tiene relación (visible) con la clase heredada. Utiliza la
private
herencia solo para implementar una funcionalidad similar que proporciona la clase Base.A diferencia de la herencia privada, la herencia protegida es una forma restringida de herencia, en la que la clase derivada es un tipo IS-A de la clase base y quiere restringir el acceso de los miembros derivados solo a la clase derivada.
fuente
Bueno, se trata de encapsular si las clases de pago manejan la facturación del pago, entonces en la clase de producto, ¿por qué necesitaría todo el proceso del proceso de facturación, es decir, el método de pago, cómo pagar dónde pagar? nada más que ese público para aquellos donde otras clases también lo usarían, protegidos para esos límites solo para extender clases. Como eres madara uchiha, lo privado es como
"limboo"
lo puedes ver (solo clasificas en una sola clase).fuente