Pregunta

Hoy he leído un libro y el autor escribió que en una clase bien diseñada la única manera de acceder a los atributos es a través de uno de que los métodos de la clase. ¿Es una idea ampliamente aceptada? ¿Por qué es tan importante para encapsular los atributos? Lo que podría ser las consecuencias de no hacerlo? Leí en alguna parte antes de que esto mejora la seguridad o algo por el estilo. Cualquier ejemplo en PHP o Java sería muy útil.

¿Fue útil?

Solución

¿Es una idea ampliamente aceptada?

En el mundo orientado a objetos, sí.

¿Por qué es tan importante para encapsular los atributos? Lo que podría ser las consecuencias de no hacerlo?

Los objetos se pretende que sean entidades cohesivos que contienen datos y el comportamiento que otros objetos pueden acceder de forma controlada a través de una interfaz pública. Si una clase no encapsula los datos y el comportamiento, ya no tiene control sobre los datos sean accesibles y no pueden cumplir con sus contratos con otros objetos implícitos en la interfaz pública.

Uno de los grandes problemas con esto es que si una clase tiene que cambiar internamente, la interfaz pública no debería tener que cambiar. De esa manera no se rompe cualquier código y otras clases puede seguir utilizándolo como antes.

Cualquier ejemplo en PHP o Java sería muy útil.

Este es un ejemplo de Java:

public class MyClass {
    // Should not be < 0
    public int importantValue;
    ...
    public void setImportantValue(int newValue) {
        if (newValue < 0) {
           throw new IllegalArgumentException("value cannot be < 0");
        }
    }
    ...
}

El problema aquí es que debido a que no he encapsulado importantValue por lo que es más que private público, cualquiera puede venir y eludir la comprobación de que puse en la incubadora para evitar que el objeto de tener un estado no válido. importantValue nunca debe ser inferior a 0, pero la falta de encapsulación hace que sea imposible evitar que sea así.

Otros consejos

¿Qué podría ser las consecuencias de no haciéndolo?

La idea detrás de la encapsulación es que todo el conocimiento de todo lo relacionado con la clase (que no sea su interfaz) está dentro de la propia clase. Por ejemplo, lo que permite el acceso directo a los atributos pone la responsabilidad de asegurarse de que las asignaciones son válidos en el código haciendo la asignación. Si la definición de lo que es cambios válidos, usted tiene que ir a través de la auditoría y todo uso de la clase para asegurarse de que cumplir. El encapsulado de una regla en un "setter" significa método que sólo tiene que cambiar en un solo lugar, y cualquier persona que llama intentar algo gracioso puede obtener una excepción lanzada en ella a cambio. Hay un montón de otras cosas que usted puede hacer cuando un cambio de atributo, y un colocador es el lugar para hacerlo.

Si o no permitir el acceso directo a los atributos que no tienen ninguna norma de obligar a ellos (por ejemplo, cualquier cosa que quepa en un número entero está bien) es una buena práctica es discutible. Supongo que el uso de captadores y definidores es una buena idea para mantener la coherencia, es decir, que siempre sabe que puede llamar setFoo() para alterar el atributo foo sin tener que mirar hacia arriba si está o no puede hacerlo directamente. También le permiten asegurar el futuro de su clase, así que si usted tiene código adicional para ejecutar, el lugar para ponerlo ya está ahí.

En lo personal, creo que tener que utilizar captadores y definidores es torpe de aspecto. Me gustaría mucho x.foo = 34 en lugar de escritura que x.setFoo(34) y esperamos el día en que algún lenguaje viene con el equivalente de trigger para los miembros que le permiten definir el código que se activa antes, después o en lugar de a las tareas.

Las opiniones sobre cómo se logra la "buena OOD" son diez centavos por docena, y los programadores y diseñadores también muy experimentados tienden a estar en desacuerdo acerca de las opciones de diseño y filosofías. Esto podría ser un motor de arranque de la llama de la guerra, si le preguntas a la gente a través de una gama de variedades de conocimiento de la lengua y paradigmas.

Y sí, en teoría son la teoría y la práctica de la misma, por lo que la elección del idioma no debe influir en el diseño de alto nivel mucho. Pero en la práctica que hacen, y buenas y malas cosas suceden debido a eso.

Permítanme añadir: Depende. La encapsulación (en un lenguaje de apoyo) le da un cierto control sobre la forma en que se utilizan las clases, por lo que puede decirle a la gente: este es el API, y usted tiene que utilizar esto. En otros idiomas (por ejemplo, Python) La diferencia entre el API oficial e informal (sujeto a cambio) Interfaces es por convención de nomenclatura única ( después de todo, todo lo que estamos los adultos que consienten aquí )

La encapsulación no es una característica de seguridad.

Otro pensamiento para reflexionar

La encapsulación con descriptores de acceso también proporciona un mejor mantenimiento en el futuro. En la respuesta de Fëanor anteriormente, funciona muy bien para hacer cumplir los controles de seguridad (suponiendo que su instVar es privado), pero puede tener benifits mucho mayor alcance.

Considere el siguiente escenario:
1) a completar su solicitud, y lo distribuirá a algún conjunto de los usuarios (internos, externos, lo que sea).
2) BigCustomerA se acerca a su equipo y quiere una pista de auditoría añadido al producto.

Si todo el mundo está utilizando los métodos de acceso en su código, esto se convierte en casi trivial de implementar. Algo así:

MyAPI Version 1.0

public class MyClass {
    private int importantValue;
    ...
    public void setImportantValue(int newValue) {
        if (newValue < 0) {
           throw new IllegalArgumentException("value cannot be < 0");
        }
        importantValue = newValue;
    }
    ...
}


V1.1 MyAPI (ahora con pistas de auditoría)

public class MyClass {
    private int importantValue;
    ...
    public void setImportantValue(int newValue) {
        if (newValue < 0) {
           throw new IllegalArgumentException("value cannot be < 0");
        }
        this.addAuditTrail("importantValue", importantValue, newValue);
        importantValue = newValue;
    }
    ...
}

Los usuarios existentes de la API de hacer ningún cambio en su código y la nueva característica (pista de auditoría) ya está disponible.
Sin encapsulación utilizando descriptores de acceso a su frente a un enorme esfuerzo de migración.


Cuando se codifica por primera vez, se va a parecer mucho trabajo. Es mucho más rápido que el tipo:. class.varName = something vs class.setVarName(something); pero si todo el mundo tomó el camino más fácil, para cobrar por solicitud de una función de BigCustomerA sería un enorme esfuerzo

Objeto Oriente Programación no es un principio que se conoce como (http://en.wikipedia.org/wiki/Open/closed_principle): POC -> Principio de abierto y cerrado . Este principio estancias para: un diseño de clase bien se deben abrir para la extensibilidad (herencia) pero cerrados para la modificación de los miembros internos (encapsulación) . Esto significa que usted no podría ser capaz de modificar el estado de un objeto sin cuidar de él.

Por lo tanto, los nuevos lenguajes sólo modifican las variables internas (campos) a través de propiedades (captadores y definidores métodos en C ++ o Java). En C # propiedades compilan a métodos en MSIL.

C #:

int _myproperty = 0;
public int MyProperty
{
    get { return _myproperty; }
    set { if (_someVarieble = someConstantValue) { _myproperty = value; } else { _myproperty = _someOtherValue; }  }    
}

C ++ / Java:

int _myproperty = 0;
public void setMyProperty(int value) 
{
  if (value = someConstantValue) { _myproperty = value; } else { _myproperty = _someOtherValue; }
}
public int getMyProperty() 
{
    return _myproperty;
}

Tome las ideas de tesis (de Cabeza Primera C # ):

  • pensar en formas de los campos se utilizan mal. ¿Qué puede ir mal si no están configurados correctamente.
  • ¿Está todo en público su clase? Pasa algún tiempo pensando acerca de encapsulación.
  • ¿Qué campos requieren el procesamiento o el cálculo? Ellos son los principales candidatos.
  • Sólo hacer que los campos y métodos pública si es necesario. Si usted no tiene una razón para declarar público algo, no lo hacen.
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top