¿Por qué es importante la cantidad de visibilidad en los métodos y atributos?


¿Por qué uno no debería dejar todos los métodos y atributos accesibles desde cualquier lugar (es decir, public)?

Puede dame un ejemplo de un problema que se puede ejecutar en si me declaró un atributo como public?

Author: Marc Towler, 2011-09-12

12 answers

Piense en los ámbitos de visibilidad como círculos internos de confianza.

Tómese a sí mismo como ejemplo y piense en qué actividades son públicas y cuáles son privadas o protegidas. Hay una serie de cosas que usted no está delegando para que nadie haga en su nombre. Hay algunos que están bien, otros para activar y hay algunos con acceso limitado.

Del mismo modo, en la programación, los ámbitos le dan herramientas para crear diferentes círculos de confianza. Además, hacer cosas privado / protegido, le da más control sobre lo que está sucediendo. Por ejemplo, puede permitir complementos de terceros que pueden extender parte de su código, mientras que pueden limitarse al alcance de hasta dónde pueden llegar.

Por lo tanto, para generalizar, los ámbitos le dan el nivel adicional de seguridad y mantiene las cosas más organizadas de lo que serían de otra manera.

 12
Author: jancha,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-07-17 16:09:02

Piensa en McDonald's como un objeto. Hay un método público bien conocido para pedir un BigMac.

Internamente va a haber algunos millones de otras llamadas para obtener los materiales para hacer ese Bigmac. No quieren que sepas cómo funciona su cadena de suministro, por lo que todo lo que obtienes es la llamada pública Gimme_a_BigMac(), y nunca te permitirían acceder a los métodos Slaughter_a_cow() o Buy_potatoes_for_fries().

Para tu propio código, que nadie verá nunca, sigue adelante y deja todo público. Pero si estás haciendo una biblioteca para que otros la reutilicen, luego vas y proteges los detalles internos. Eso deja a McDonald's libre de cambiar a tener Scotty viga sobre una empanada en lugar de tener que llamar a una compañía de camiones para entregar la carne por tierra. El usuario final nunca conoce la diferencia, simplemente obtiene su BigMac. Pero internamente todo podría cambiar fundamentalmente.

 146
Author: Marc B,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-09-12 17:57:39

¿Por qué uno no debería dejar todos los métodos y atributos accesibles desde cualquier lugar (es decir, públicos)?

Porque eso es demasiado caro.

Cada método público que hago tiene que ser cuidadosamente diseñado y luego aprobado por un equipo de arquitectos, tiene que ser implementado {[6] } para ser robusto frente a personas que llaman arbitrariamente hostiles o con errores , tiene que ser completamente probado , todos los problemas encontrados durante regresión suites añadido, el método tiene que ser documentado, la documentación tiene que ser traducido en al menos doce idiomas diferentes.

El mayor costo de todo es: el método tiene que mantenerse, sin cambios, por los siglos de los siglos, amén. Si decido en la próxima versión que no me gustó lo que hizo ese método, no puedo cambiarlo porque los clientes ahora confían en él. Romper la compatibilidad hacia atrás de un método público impone costes a usuarios y detesto hacer eso. Vivir con un mal diseño o implementación de un método público impone altos costos a los diseñadores, probadores e implementadores de la próxima versión.

Un método público puede costar fácilmente miles o incluso decenas de miles de dólares. Hacer un centenar de ellos en una clase y eso es un millón de dólares de la clase allí.

Los métodos privados no tienen ninguno de esos costos. Gastar el dinero de los accionistas sabiamente; hacer todo privado que posiblemente puede.

 45
Author: Eric Lippert,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-09-12 18:20:13

Porque eso viola el concepto de encapsulación, un principio clave de OOP.

 10
Author: Daniel A. White,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-09-12 17:24:42

¿Un riesgo que corres, dices?

<?php

class Foo
{
    /**
     * @var SomeObject
     */
    public $bar;
}

Su código indica que $bar debe contener una instancia de objeto SomeObject. Sin embargo, cualquier persona que use su código podría hacer

$myFoo->bar = new SomeOtherObject();

... y cualquier código que dependa de que Foo:: bar bar sea SomeObject se rompería. Con getters y setters y propiedades protegidas, puede hacer cumplir esta expectativa:

<?php

class Foo
{
    /**
     * @var SomeObject
     */
    protected $bar;

    public function setBar(SomeObject $bar)
    {
        $this->bar = $bar;
    }
}

Ahora puede estar seguro de que cada vez que se establezca Foo:: bar bar, será con una instancia de objeto SomeObject.

 9
Author: Problematic,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-09-12 17:34:02

Al ocultar los detalles de la implementación, también evita que un objeto entre en un estado inconsistente.

Aquí hay un ejemplo artificial de una pila (pseudo código).

public class Stack {

  public List stack = new List();
  public int currentStackPosition = 0;

  public String pop() {
    if (currentStackPosition-1 >= 0) {
      currentStackPosition--;
      return stack.remove(currentStackPosition + 1);
    } else {
      return null;
    }
  }

  public void push(String value) {
    currentStackPosition++;
    stack.add(value);
  }
}

Si hace que ambas variables sean privadas, la implementación funciona bien. Pero si es público, puede romperlo fácilmente simplemente estableciendo un valor incorrecto para currentStackPosition o modificando directamente la Lista.

Si solo expone las funciones, proporciona un contrato confiable que otros pueden usar y confianza. Exponer la implementación solo hacer que sea una cosa que podría funcionar de nadie se mete con ella.

 4
Author: OliverS,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-09-13 06:59:04

La encapsulación no es necesaria en ningún idioma, pero es útil. La encapsulación se utiliza para minimizar el número de dependencias potenciales con la mayor probabilidad de propagación del cambio también ayuda a prevenir inconsistencias:

Ejemplo simple: Supongamos que hicimos una clase de rectángulo que contenía cuatro variables: longitud, ancho, área y perímetro. Tenga en cuenta que el área y el perímetro se derivan de la longitud y el ancho (normalmente no haría variables para ellos), de modo que cambiar la longitud cambiaría tanto el área como el perímetro.

Si no se utiliza la información adecuada ocultación (encapsulación), entonces otro programa que utiliza esa clase Rectángulo podría alterar la longitud sin alterar el área, y tendría un Rectángulo inconsistente. Sin encapsulación, sería posible crear un Rectángulo con una longitud de 1 y una anchura de 3, y tener un área de 32345.

Usando encapsulación, podemos crear una función que, si un programa quiere cambiar la longitud del rectángulo, que el objeto actualizaría adecuadamente su área y perímetro sin ser inconsistente.

La encapsulación elimina las posibilidades de inconsistencia, y cambia la responsabilidad de mantenerse consistente sobre el objeto en sí en lugar de un programa que lo utiliza.

Sin embargo, al mismo tiempo, la encapsulación es a veces una mala idea, y la planificación del movimiento y la colisión (en la programación de juegos) son áreas donde es particularmente probable que esto ocurra caso.

El problema es que la encapsulación es fantástica en lugares donde se necesita, pero es terrible cuando se aplica en lugares donde no se necesita, como cuando hay propiedades globales que necesitan ser mantenidas por un grupo de encapsulación, Ya que la encapsulación forzada OOP no importa qué, estás atascado. Por ejemplo, hay muchas propiedades de objetos que no son locales, por ejemplo, cualquier tipo de consistencia global. Lo que suele suceder en OOP es que cada objeto tiene que codificar su visión de la condición de consistencia global, y hacer su parte para ayudar a mantener las propiedades globales correctas. Esto puede ser divertido si realmente necesita la encapsulación, para permitir implementaciones alternativas. Pero si no lo necesitas, terminas escribiendo un montón de código muy complicado en varios lugares que básicamente hace lo mismo. Todo parece encapsulado, pero en realidad es completamente interdependiente.

 2
Author: Mouna Cheikhna,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-09-13 08:28:50

Bueno, de hecho puede tener todo público y no se rompe la encapsulación cuando se indica claramente, lo que es el contrato, la forma correcta de utilizar los objetos. Tal vez no atributos, pero los métodos son a menudo más ocultos de lo que tienen que ser.

Recuerde, que no es usted, el diseñador de API, que está rompiendo la encapsulación al hacer las cosas públicas. Son los usuarios de la clase los que pueden hacerlo, llamando a métodos internos en su aplicación. Puedes abofetear sus manos para tratar de hacerlo (es decir, declarar métodos privados), o pasar la responsabilidad a ellos (por ejemplo, prefijando métodos no API con "_"). ¿Realmente te importa si alguien rompe su código usando tu biblioteca de la otra manera que le aconsejaste que hiciera? Yo no.

Hacer que casi todo sea privado o final, o dejarlos sin documentación de API, por otro lado, es una forma de desalentar la extensibilidad y la retroalimentación en el código abierto. Su código se puede utilizar de una manera que usted ni siquiera se le ocurrió, lo que podría no ser el caso cuando todo está bloqueado (por ejemplo, métodos sellados por defecto en C#).

 2
Author: pwes,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-09-14 11:43:44

El único problema que puede encontrar es que la gente lo verá como "no cool" si no usa Private o Protected o Abstract Static Final Interface o lo que sea. Estas cosas son como ropa de diseñador o gadgets de Apple: la gente las compra no porque lo necesiten, sino solo para mantenerse al día con los demás.

Sí, la encapsulación es un concepto teórico importante, pero en la práctica "privado" y los amigos rara vez tienen sentido. Ellos podrían tener algún sentido en Java o C#, pero en un lenguaje de scripting como PHP usar "private" o "protected" es una estupidez, porque la encapsulación se inventa para ser comprobada por un compilador, que no existe en PHP. Más detalles.

Ver también esta excelente respuesta y @troelskn y @ mario comentarios sobre aquí

 1
Author: user187291,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 10:30:35

La visibilidad es algo que puedes usar por tu propio bien, para ayudarte a no romper tu propio código. Y si lo usas bien, ayudarás a otros (que están usando tu código) que no rompen su propio código (al no usar tu código correctamente).

El ejemplo más simple, ampliamente conocido, en mi opinión es el patrón Singleton. Es un patrón, porque es un problema común. (Definición de patrón de Wikipedia:

Es una forma formal de documentar una solución a un problema de diseño

Definición del patrón Singleton en Wikipedia:

En ingeniería de software, el patrón singleton es un patrón de diseño utilizado para implementar el concepto matemático de un singleton, restringiendo la instanciación de una clase a un objeto. Esto es útil cuando se necesita exactamente un objeto para coordinar acciones en todo el sistema.

Http://en.wikipedia.org/wiki/Singleton_pattern

La implementación del patrón utiliza un constructor private . Si no hace que el constructor sea privado, cualquiera podría crear una nueva instancia por error y romper el punto de tener solo una instancia.

 1
Author: Iravanchi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-09-16 06:41:20

Puede pensar que las respuestas anteriores son "teóricas", si usa propiedades public en Entidades Doctrine2, rompe la carga perezosa.

 1
Author: Francesco,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-09-17 10:58:12

Para salvarte de ti mismo!

Ha habido algunas respuestas excelentes arriba, pero quería agregar un poco. Esto se llama principio de privilegio mínimo . Con menos privilegios, menos entidades tienen autoridad para romper cosas. Romper cosas es malo.

Si sigues el principio del menor privilegio, el principio del menor conocimiento (o Ley de Deméter) y principio de responsabilidad única no están muy lejos. Desde tu clase escribiste para descargar los últimos resultados de fútbol han seguido este principio, y tienes que sondear sus datos en lugar de volcarlos directamente a tu interfaz, copiar y pegar toda la clase en tu próximo proyecto, ahorrando tiempo de desarrollo. Ahorrar tiempo de desarrollo es bueno.

Si tienes suerte, volverás a este código en 6 meses para corregir un pequeño error, después de haber hecho gigaquads de dinero con él. El yo futuro tomará el nombre del yo anterior en vano por no seguir los principios anteriores, y caerá víctima de una violación del principio del menor asombro. Es decir, su error es un error de análisis en el modelo de puntuación de fútbol, pero como no siguió LOD y SRP, está sorprendido por el hecho de que está haciendo análisis XML en línea con su generación de salida. Hay cosas mucho mejores en la vida por las que asombrarse que la horrorosidad de su propio código. Confía en mí, lo sé.

Puesto que usted siguió todos los principios y documentó su código, usted trabaja dos horas todos los jueves por la tarde en la programación de mantenimiento, y el resto del tiempo navegando.

 1
Author: wjl,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-04-15 08:30:03