2010-02-17 8 views
50

Qué es mejor la práctica y por qué: el acceso a las variables de clase base a través de un campo protegido o un captador pública en el ámbito privado.campos protegidos de Java vs captadores públicas

(El comprador será pública independientemente) no es preferido

+1

[Los campos protegidos en la clase base son malos] (http://stackoverflow.com/questions/3182653/are-protected-members-fields-really-that-bad). – RBT

Respuesta

53

Si no va a ser un captador pública de todos modos, ¿por qué querrías para exponer el campo en sí más ampliamente de lo absolutamente necesario? Eso significa que se puede escribir inmediatamente por subclases (a menos que sea final para comenzar).

Personalmente me gustan todos mis campos sean privadas: proporciona una separación limpia entre el API y la aplicación. Considero que la relación entre una superclase y una subclase es similar a la de una persona que llama y llama: los cambios en la implementación subyacente no deberían romper las subclases más de lo que deberían interrumpir a las personas que llaman. El nombre de un campo es un detalle de implementación que no debería afectar otras clases.

Es cierto que mi punto de vista es a veces visto como algo extremo ...

+0

En mi experiencia ciertamente limitada, no he encontrado buenas razones para usar campos protegidos, y siempre parece causar otros problemas. Estoy de acuerdo en que es mejor hacerlos privados en casi todos los casos. – Feanor

+0

@ Jon. ¿Podría proporcionar un ejemplo/ilustración de trabajo para este escenario donde las dos variables/métodos en superclase se usan en la subclase? Muy agradecido con usted si pudiera responder de nuevo – Deepak

+7

@Deepak: me temo que no tener tiempo para dar un ejemplo completo por cada respuesta de Java que doy. ¿Por qué no lo intentas tú mismo y si tienes problemas, haces una pregunta? –

8

Acceso Directo campo. Use public o protected setters and getters.

El comprador no tiene que ser public - si Wan para ocultar los datos de "extraños", pero dar los datos a subclases, utilice protected

14

Usted debe programar siempre en contra de la API pública de una clase, es decir, utilizar los métodos públicos.

La razón es simple. Algún día en el futuro, usted u otra persona podrían querer cambiar la implementación. Esto siempre debería ser posible. Si confías en la variable de instancia, te limitas.

Además, cuando se accede a la variable, no se puede controlar de sólo lectura si esa variable está ni se puede añadir cheques cuando se cambia esta variable.

Si utiliza setters/captadores, se puede añadir Allways validación, verificación, etc más adelante. También puede proporcionar un getter para que solo una variable sea de solo lectura.

+2

Si alguien * expone * una variable, deberían tratarla como inmutable tanto como deberían hacerlo con un método público/protegido. Si alguien expone un campo y luego lo cambia, claramente no se preocupan por romper otros desarrolladores en primer lugar, y posiblemente también cambie los métodos :( –

+0

Es cierto. Es por eso que agregué tantos "debería" a mi comentario :) Pero la mayoría de las veces es más fácil mantener un método público existente y simplemente agregar una versión especial/sobrecargada, por lo que prefiero las variables privadas (excepto las constantes finales estáticas públicas) – phisch

3

Algunas de las recomendaciones de Sun para controlar el acceso a los campos son here. Tenga en cuenta que proteger un campo también lo expone al paquete, no solo a las subclases. En general, como se indica en el enlace anterior, los campos deben ser privados a menos que haya una muy buena razón para no hacerlo.

+1

+1 por mencionar que 'protegido 'implica el * nivel de acceso privado del paquete * – ifloop

0

Acceso a los campos protegidos de una subclase es una de las maneras que la herencia viola la encapsulación. Usar la API pública es mejor por esta razón.

3

eficaz de Java 2ª edición dice

Tema 13: Minimizar la accesibilidad de las clases y los miembros

La regla de oro es simple: hacer cada clase o miembro tan inaccesible como posible. En otras palabras, use el nivel de acceso más bajo posible compatible con el funcionamiento correcto del software que está escribiendo.

Así que si no está seguro de por qué necesita un miembro protegido de la clase (es decir, no necesita que las subclases o clases del mismo paquete tengan acceso al campo), entonces declare que es privado. Si deseas configurarlo desde fuera de la clase, crea un setter público.

Sin embargo, si su miembro es final, protegerlo podría estar bien en algunos casos (es decir, no revela información confidencial).

Un problema potencial de seguridad que me gustaría mencionar es que si tiene una matriz declarada protegida final (incluso pública final), la matriz de referencia es final (no se puede modificar), pero los objetos contenidos en la matriz no son finales (un intruso podría cambiar el contenido de la matriz).


Si sabes C++, usted probablemente sabe que

const int * someMember

es diferente de

int * const someMember

Esta última es igual que la matriz final en java.


La corrección para el agujero de seguridad mencionado es para devolver una copia en profundidad de la matriz o devolverlo como una única lista leer.

1

Generalmente, debe usar las recomendaciones de Sun. Hay una gran excepción: si estás programando para Android.

El motivo es el rendimiento. Con cada invocación de método virtual, hay una sobrecarga implicada en el uso de la tabla de búsqueda para encaminar el método a su objeto. Esta sobrecarga no está involucrada al acceder a una variable local.

Éstos son algunos enlaces que explican esto en un poco más de profundidad:

http://developer.android.com/training/articles/perf-tips.html#GettersSetters

http://blog.leocad.io/why-you-shouldnt-use-getters-and-setters-on-android/

Es importante saber lo que estamos tratando de lograr:

  1. El El valor del campo debe ser accesible para el código del cliente, utilizando una interfaz pública.
  2. El campo está destinado a ser utilizado por subclases.

En simple ol 'Java, getters y setters realizan ambas tareas. Pero Android es diferente. Si está haciendo # 1, entonces debe usar getters y setters públicos. Si está haciendo # 2, entonces debería usar campos protegidos. Si estás haciendo ambas cosas, usa ambas.

Cuestiones relacionadas