2010-07-05 20 views
12

Según tengo entendido, el término "referential transparency" realmente solo se puede aplicar al código funcional. Sin embargo, una llamada de método en un objeto en código orientado a objetos puede tener una propiedad similar, que es que el valor de retorno del método y el estado del objeto después de una llamada a un método depende únicamente del estado del objeto antes de la llamada y los argumentos del método¿Cómo llamar el equivalente de OOP de "transparencia referencial"?

es decir, la transparencia referencial funcional:

i = foo(n, m); 
// return value depends only on n, m 

OO "transparencia referencial":

i = obj.foo(n, m); 
// return value, and subsequent state of obj, depends 
// only on initial state of obj, n, m 

¿Hay un nombre para esta propiedad?

Si el estado de obj no cambia durante la llamada a foo(), entonces el "orientado a objetos" El estilo es equivalente a la forma funcional si se admite function overloading ya que podría ser reescrita como:

i = foo(obj, n, m); 
// return value depends only on obj, n, m 

Sin embargo , es bastante común para el estado de obj a cambiar de una llamada a un método, así que no estoy seguro si esto ayuda a que el análisis ...

Respuesta

16

Su error es pensar que FP y OO son de alguna manera fundamentalmente diferentes. La "versión OO" de la transparencia referencial es solo transparencia referencial.

Una expresión e es referencialmente transparente si y solo si e se puede reemplazar con su resultado evaluado sin afectar el comportamiento del programa.

Así que si tiene una expresión o.foo(a), entonces es referencialmente transparente si puede modificar su código para reemplazarlo con el resultado de la llamada, sin cambiar el comportamiento de su programa. Obviamente, si o.foo es nulo, no puedes hacer eso. Lo mismo si modifica el estado interno de o. Entonces, la única forma de que o.foo(a) sea referencialmente transparente es si el resultado es una función deo y a.

En mi opinión, "código funcional", es sinónimo de "código de referencia referencial".

+3

Además, si a) su programa depende de la identidad del objeto del resultado de 'o.foo (a) ', o b)' o.foo (a) 'tiene algún efecto secundario como E/S, no puede reemplazar la llamada. – retronym

+0

Supongo que es justo decir que es posible una transparencia referencial completa con el código OO. (El getter estándar probablemente tendrá esta propiedad). Pero mi pregunta principal es si hay un nombre para la propiedad más débil pero útil que sigue a una llamada a un método, el valor de retorno y el estado final de 'o' depende solo de la estado inicial de 'o' y los argumentos del método. – mjs

+0

Los captadores estándar son enfáticamente ** no ** referencialmente transparentes. La transparencia referencial significa que sus resultados dependen de los parámetros pasados ​​** solo **. Un getter ** no tiene ** parámetro pass-in (a menos que quiera comenzar a hablar sobre parámetros implícitos como 'this' /' self' en cuyo caso le falta el punto de la parte "transparent") y su valor devuelto depende del estado del objeto involucrado en la llamada, una entidad externa a la función. La transparencia referencial es, básicamente, "obtienes lo que ves y nada más". Si hay partes invisibles, eso no es transparente. –

2

el estado del objeto después de una llamada al método depende sólo del estado del ob antes de la llamada, y los argumentos del método.

supongo que se podría decir que el método no tiene dependencias externas.

Sin embargo, a diferencia de la transparencia referencial, no estoy seguro de lo que esto te beneficia. Supongo que significa que el método es fácilmente comprobable.

+0

Sí, estaba pensando en cómo esta propiedad ayuda con las pruebas, y también cómo ayuda a uno a razonar sobre el código. – mjs

+0

No estoy seguro Estoy de acuerdo con la última afirmación: si una de las dependencias es el estado de inicio del objeto, es muy * difícil * evaluar ya que enumerar todos los estados posibles para cualquier objeto no trivial hace que seleccionar casos de prueba adecuados sea muy difícil (Estoy de acuerdo en que tener dependencias externas hace que el espacio de entrada sea aún mayor, hasta el punto de explosión combinatoria) – Paolo

+0

@Paolo estuvo de acuerdo. Sin embargo, estarás de acuerdo en que al menos es comprobable en principio, a diferencia de decir un método que llama 'DateTime.Now' – AakashM

4

El término funcional sería transparencia referencial como usted dice. Humildemente, propondría que la forma que ha descrito aquí con los resultados en función de los argumentos del método más el estado del objeto se denomine opacidad referencial.

4

No creo que la propiedad que describió en el escenario OO le brinde algo similar a lo que transparencia referencial tiene en programación funcional. Usted describió una propiedad donde el método foo modifica sólo el estado del objeto obj en la siguiente llamada:

i = obj.foo(n, m); 

Sin embargo, si usted tiene otro objeto que hace referencia a obj entonces la llamada a foo también modifica el comportamiento de la otra objeto. Como las referencias entre objetos son esenciales en OO (lo que significa que es un problema que no puede evitar fácilmente), esto significa que la propiedad que describió no le dice mucho sobre el código. Por ejemplo:

a = new Other(obj); 
i = obj.foo(n, m); // changes state of 'obj' and 'a' 

Si el método foo era referencialmente transparente (no modificar cualquier estado - acaba de regresar algunos resultados), entonces eso sería una propiedad interesante - porque no sería modificar el estado de a.

+0

. Aprecio tu punto de que si el estado de obj cambia, teóricamente puede pasar cualquier cosa cuando Se llama a foo() ya que obj podría tener conexiones con cualquier otro objeto en el sistema, y ​​no lo consideré al plantear la pregunta. Sin embargo, creo que la OOP "transparencia referencial" sigue siendo un concepto significativo y útil si los cambios a obj están restringidos a sus propios tipos primitivos o escalares. Esta propiedad hace que sea más fácil probar y razonar sobre el código, por ejemplo. – mjs

+1

"entonces teóricamente puede pasar cualquier cosa cuando foo()" golpea el clavo en la cabeza. Como esto es cierto, se vuelve mucho más difícil estar seguro acerca del comportamiento de un programa, incluida una llamada a foo(). En términos prácticos, los programadores deben hacer más trabajo para asegurarse de la modularidad y seguridad de dicho objeto. Además, a menudo es una preocupación global: debe anteponer su certeza a "Asumir que la clase se usa como se pretende ..." – MtnViewMark