¿Cómo evolucionó OOP para incluir la noción de propiedades?


11

Vengo de un entorno de C ++ y estoy sacando todo C # en mi trabajo actual y acabo de leer muchas preguntas y respuestas sobre cuál es la diferencia entre los campos públicos y las propiedades y todo lo relacionado con variaciones y encarnaciones de este pregunta básica (por ejemplo, esta publicación SO y todas las preguntas relacionadas relacionadas ). Todas esas preguntas se abordan en términos de diferencias prácticas que dan por sentado la existencia de un sistema de propiedad, pero creo que sería bueno abordar este tema en términos de lo que los diseñadores de todos los idiomas que decidieron admitir propiedades en el primer lugar estaba pensando (mira la lista en el artículo de Wikipedia aquí) ¿Cómo evolucionó OOP desde C ++ / Java para extenderse a lo que el artículo de Wikipedia identifica de manera interesante como un punto medio entre los métodos y los datos de los miembros:

"Es decir, las propiedades son intermedias entre el código de miembro (métodos) y los datos de miembro (variables de instancia) de la clase, y las propiedades proporcionan un mayor nivel de encapsulación que los campos públicos".

MSDN agrega más antecedentes:

"Aunque las propiedades son técnicamente muy similares a los métodos, son bastante diferentes en términos de sus escenarios de uso. Deben verse como campos inteligentes. Tienen la sintaxis de llamada de los campos y la flexibilidad de los métodos".

Me gustaría saber cómo se llegó a que este nivel intermedio de encapsulación resultó útil para la programación en general. Supongo que este concepto no estaba presente en la primera encarnación de lenguajes de programación que expresaban el paradigma OOP.


8
La función de lenguaje simple es simplemente azúcar sintáctica conveniente para los métodos getter y setter. Si hay razones más profundas detrás de la interpretación y la terminología, no lo sé.

En una ronda de expertos en OO, el título de su pregunta puede provocar, y puede distraer de lo que realmente estaba preguntando. No es que me considere un experto en OO, solo soy un "usuario de OO" durante varios años.
Doc Brown

Es un detalle sintáctico que he echado de menos al pasar de 'métodos sin parámetros' en Python a C ++. BMI = bob.weight/sq(bob.height)se lee mejor sin ()IMO.
OJFord

Creo que las propiedades estaban en el Visual Basic original (no .net), como una forma de configurar el objeto Active X (COM). La cuadrícula de propiedades en esta herramienta probablemente tuvo algo que ver con la adopción de propiedades en idiomas. Tenga en cuenta que el Visual Basic original no estaba orientado a objetos de muchas maneras, pero tenía la capacidad de crear algo así como clases.
Frank Hileman

Continuando: la ventana de propiedades era una forma de configurar objetos sin escribir código. Se llamaba desarrollo RAD. Este enlace contiene una captura de pantalla de la ventana de propiedades de VB6: microsoft.com/mspress/books/WW/sampchap/4068.aspx
Frank Hileman

Respuestas:


5

Se trata de encapsulación y el principio de acceso uniforme.

Un objeto debería poder responder a un mensaje devolviendo datos existentes o ejecutando un método, pero el remitente no debería poder decir cuál es cuál. O si ve esto desde el lado del remitente: el remitente debe poder acceder a los datos existentes o ejecutar un método a través de una interfaz uniforme.

Hay varias formas de lograr esto:

  • deshacerse de los datos por completo, solo tiene métodos (Newspeak hace esto)

    • una forma menos radical de lo anterior: deshacerse de los datos en la interfaz pública , es decir, hacer que los datos siempre sean privados, en la interfaz pública, solo exponer métodos (Smalltalk, Ruby hacen esto)
  • deshacerse de los métodos por completo, solo tener datos (Self hace esto, los "métodos" son solo Methodobjetos asignados a variables de instancia, las variables de instancia se buscan con despacho virtual)

  • no hace distinción sintáctica o semántica entre métodos y datos (Scala hace esto, acceder a un campo es sintácticamente indistinguible de llamar a un método sin una lista de argumentos ( foo.bar), asignar a un campo es sintácticamente indistinguible de llamar a un método especialmente nombrado ( foo.bar = baz) es lo mismo como, por foo.bar_=(baz)ejemplo, llamar a un método llamado foo_=, y los valores de solo lectura pueden ser anulados o implementados por un método sin lista de parámetros (es decir, val fooen una superclase puede ser anulado (o abstract valimplementado) en una subclase con un método def foo)

Java, sin embargo, no sigue el Principio de acceso uniforme. En Java, es posible distinguir entre acceder a los datos y ejecutar un método. foo.bares diferente de foo.bar(). La razón de esto es que los campos y métodos son semántica y sintácticamente distintos.

C # intenta solucionar esto agregando propiedades al lenguaje, básicamente métodos que parecen campos. Sin embargo, las llamadas a métodos todavía se ven y se sienten diferentes de los accesos de campo y propiedad. Los campos y las propiedades ahora tienen acceso uniforme, pero los métodos aún no.

Por lo tanto, esto en realidad no soluciona el problema: ¡no puede solucionar tener dos formas diferentes de acceder a las cosas agregando una tercera forma de acceder a las cosas! Incluso si esa tercera forma se parece a una de las otras dos formas, todavía tendrá (al menos) dos formas diferentes. Solo puede solucionarlo eliminando todas las formas diferentes, excepto una, o eliminando las diferencias.

Está perfectamente bien tener un lenguaje con métodos, propiedades y campos, pero los tres deberían tener acceso uniforme.


1
¿Por qué usted (y otros) piensan que es tan importante mantener el Acceso Uniforme? Con un método, es posible que desee darle parámetros para cambiar lo que hace o actúa. Con un campo o propiedad que no tiene esta capacidad, generalmente solo devuelve datos (aunque una propiedad se puede implementar como un método en lugar de exponer un campo privado). Eso me parece intuitivo, quizás solo porque estoy acostumbrado, pero ¿qué ganarías en elegancia o productividad al imponer un acceso uniforme? ¿Teme que esté filtrando detalles de implementación fuera de la clase?
Mike apoya a Mónica el

1
El UAP se trata de reservar la libertad de cambiar los detalles de implementación sin romper la interfaz pública. El ejemplo habitual es agregar registros. Si ofrezco acceso a través de un método, puedo cambiar trivialmente las partes internas del método para escribir en un registro. Con un campo público, no puedo agregar el registro sin convertirlo primero en un método, que rompe todo el código del cliente. Si no se pueden arriesgar cambios importantes, es imprescindible utilizar métodos. Las propiedades son el compromiso óptimo porque son métodos completos pero parecen campos. La adhesión al UAP mejora la encapsulación y reduce el acoplamiento estrecho.
amon

Muchas buenas respuestas a esta pregunta, pero creo que esta dio en el clavo sacando los aspectos más fundamentales de la naturaleza de los lenguajes de programación y elaborando sobre el concepto formal relevante de UAP. Sólido
jxramos

18

Bueno, no estoy 100% seguro, pero creo que las cosas son probablemente más simples de lo que esperas. De las escuelas de modelado OO de los años 90, hubo una demanda de clases de modelado con atributos de miembros encapsulados, y cuando se implementa en lenguajes como C ++ o Java, esto generalmente conduce a un código con muchos captadores y establecedores, por lo que hay mucho "ruido" código para un requisito relativamente simple. Tenga en cuenta que la mayoría de los idiomas enumerados en su artículo vinculado de Wikipedia (probablemente todos no verificaron esto) comenzaron a introducir "propiedades" de los objetos a fines de los 90 o más tarde.

Supongo que esa fue la razón principal por la que los diseñadores de idiomas decidieron agregar un poco de azúcar sintáctica para reducir ese ruido. Y aunque las propiedades seguramente no son un "concepto OO central", al menos tienen algo que ver con la orientación a objetos. No muestran "una evolución de OOP" (como supone el título de su pregunta), pero admiten el modelado de OO en el nivel del lenguaje de programación para facilitar la implementación.


No tiene nada que ver con la programación orientada a objetos, excepto en el sentido de que una propiedad es una abstracción de un campo, y los campos son parte de la programación orientada a objetos. Pero las propiedades no son necesarias para la programación orientada a objetos, como se observa correctamente.
Frank Hileman

2
@FrankHileman: "una propiedad es una abstracción de un campo, y los campos son parte de la programación orientada a objetos", bueno, eso me parece que está de acuerdo en que el concepto tiene al menos algo que ver con OOP. ¿Y por eso me rechazaste?
Doc Brown

3
jajaja ¿Puedes culparlo? Se quitó el inodoro y se golpeó la cabeza con el lavabo. De todos modos ... La forma en que siempre lo vi fue que las propiedades no son estrictamente de OO. Ayudan con la encapsulación y la encapsulación ayuda con OO.
MetaFight

1
¡Decir ah! Esta es una gran introducción a programmers.stackexchange para mí. Lol, mucho más acalorado que mi experiencia equivalente en el flujo de stackover OL simple :-p ¡Buena manera de mezclar el día!
jxramos


11

Lo tienes al revés (más o menos). El cálculo Lambda existe como la base formal principal para los lenguajes de programación, y lo ha sido durante décadas. No tiene campos.

Para modelar el estado mutable, necesita hacer dos abstracciones. Uno representa establecer algún estado, y otro que recupera ese estado (Capítulo 13 en mi versión de TaPL como referencia). ¿Suena familiar? Desde un fondo teórico , OO no evolucionó para tener estas cosas. OO leyó Lenguajes de programación 101 e hizo un pequeño paso adelante.

Desde una perspectiva práctica , hay dos motivaciones bastante claras. Usted viene de un entorno C ++, entonces, ¿qué tendría que suceder si tuviera un campo público? Digamos ... el texto en un cuadro de texto. ¿Qué sucede cuando quieres cambiar tu diseño para que "cada vez que este cuadro de texto cambie, bla? Puedes eliminar ese campo, hacer una función o dos y conectar esa lógica, ya que no puedes confiar en que los desarrolladores llamen a sí mismos "UpdateTextbox". Este es un cambio muy importante en su API (y desafortunadamente aún es un cambio importante en la implementación de propiedades de .NET). Este tipo de comportamiento está por todas partes en la API de Windows. Dado que eso es un gran problema en Microsoft, C # probablemente quería hacerlo menos doloroso.

La otra gran motivación es Java Beans y sus parientes. Se construyeron varios marcos para usar la reflexión de Java para buscar GetXy SetXemparejar y tratarlos efectivamente como propiedades modernas. Pero como no eran construcciones de lenguaje reales, estos marcos eran frágiles y poco amables. Si escribes un nombre, las cosas se romperían en silencio. Si uno fue refactorizado, nada movió el otro lado de la propiedad. Y hacer todo el campo / get / set repetitivo fue detallado y tedioso (¡incluso para Java!). Dado que C # se desarrolló en gran medida como "Java con lecciones aprendidas", ese tipo de dolor fue una de esas lecciones.

Pero lo más importante es que el concepto de propiedad ha sido exitoso. Es fácil de entender, es fácil de usar. Estos ayudan enormemente a la adopción, y como herramienta , los programadores han descubierto que las propiedades resuelven un subconjunto de problemas de manera más limpia que las funciones o los campos.


77
Te rechacé principalmente por demasiada referencia a basura formal irrelevante. Las implementaciones reales de lenguajes de programación tienen cosas mucho más serias a considerar que si su modelo se incluyó o no en el cálculo lambda.
DeadMG

99
@DeadMG: eso es cierto, pero por otro lado, los implementadores de lenguaje de programación siempre estarán familiarizados con esa basura formal irrelevante . Pensar que no impactó sus diseños es ingenuo.
Telastyn

3
Esto definitivamente no es una "mierda formal irrelevante". Sin embargo, el cálculo lambda puede no haberse considerado mucho para los primeros lenguajes de programación. Si es así, las CPU probablemente estarían más orientadas hacia esa mentalidad.
Frank Hileman

3
@FrankHileman - Estoy bastante seguro de que Lisp lo consideró ...
Telastyn

44
@Telastyn, sí, y no se suponía que Lisp fuera originalmente un lenguaje de programación, ¿recuerdas?
Frank Hileman

3

En .net específicamente, las propiedades se originan en los viejos días de Visual Basic que, como sucede, no estaban orientados a objetos en la forma en que lo pensamos hoy. Fue construido en gran medida en torno al nuevo sistema COM que trataba superficialmente todo no necesariamente como clases sino en términos de componentes que expondrían propiedades a las que se podía acceder tanto en código como en editores gráficos. Cuando VB y el C # recién creado se fusionaron en .net, VB obtuvo una gran cantidad de características OOP y mantuvieron propiedades, ya que eliminarlas sería como un paso atrás: imagínese si la herramienta de actualización automática de código que tenían en Visual Studio hubiera sido reemplazando todas sus propiedades con getters y setters y estaba rompiendo la compatibilidad con todas las bibliotecas COM. Sería lógico apoyarlos en todos.


No creo que deba ignorar la ascendencia de C # que vino de Delphi y de antes, Object Pascal y Turbo Pascal with Objects. Estos estaban orientados a objetos y tenían propiedades (aunque no recuerdo si OP tenía propiedades de TP5.5 o si se agregaron; presumiblemente, Anders las continuó en C # porque eran pragmáticamente una buena idea.
amaca

Muy interesante que usted haya sido el único en llegar al aspecto componente de esta pregunta. Acabo de agregar un comentario a mi pregunta que se vincula a un sitio que enumeró propiedades como parte de algún modelo de propiedad, método y evento que satisface C #. Luego volví a buscar en la página de mi pregunta el "componente" que generaba algunos falsos positivos, pero creo que tu respuesta se superpone con lo que he vinculado.
jxramos

3

Las propiedades no tienen nada que ver con la programación orientada a objetos, porque las propiedades son solo azúcar sintáctico. Las propiedades parecen campos superficialmente, y en el mundo .net, se recomienda que se comporten como campos de alguna manera, pero no son campos en ningún sentido. Las propiedades son azúcar sintáctica para uno o dos métodos: uno para obtener un valor y otro para establecer un valor. Se puede omitir el método set o el método get, pero no ambos. Es posible que no haya ningún campo que almacene el valor devuelto por el método get. Debido a que comparten una sintaxis con los campos y porque a menudo usan campos, las personas asocian propiedades con los campos.

Las propiedades tienen ventajas sobre los campos:

  • En un método de conjunto de propiedades, antes de que se almacene un valor de propiedad, el nuevo valor o el estado del objeto pueden verificarse contra un conjunto de condiciones previas o invariantes.
  • Puede existir un método de obtención de propiedades por conveniencia, si la recuperación del valor de la propiedad puede considerarse lógicamente equivalente a la recuperación de un valor de campo.
  • Un método de conjunto de propiedades puede realizar otras operaciones, como notificar a un objeto padre u escuchar objetos de un cambio en un valor de propiedad.

Como las propiedades son la abstracción de los campos y, por conveniencia sintáctica, los lenguajes como C # adoptaron la sintaxis de campo para las propiedades.


2
Primera línea del artículo de Wikipedia. "Una propiedad, en algunos lenguajes de programación orientados a objetos, es un tipo especial de miembro de clase ...". Entonces, tu primera oración está completamente equivocada. Y la parte restante no responde la pregunta.
Doc Brown

1
@DocBrown: respuesta interesante. Muchos artículos de Wikipedia son claramente incorrectos. ¿Asumo que estás defendiendo al autor de este artículo específico?
Frank Hileman

1
No todas las características de los lenguajes de programación orientados a objetos están relacionadas con conceptos orientados a objetos.
Frank Hileman

1
Eso no cambia el hecho de que no está respondiendo la pregunta.
Doc Brown

3
Cabe señalar que no solo el configurador es opcional. Puede tener solo propiedades de setter.
Telastyn

2

Es una cuestión de implementación versus implicación . Las propiedades estaban en OOP antes de que C ++ o Java llegaran a la escena (estaban allí, con cierta aspereza en los bordes, en Simula, y son fundamentales para Smalltalk). Las entidades con propiedades son conceptualmente diferentes de los valores con código adjunto. Los prefijos get & set en algunas convenciones de idiomas solo sirven para enturbiar las aguas; te hacen consciente de la diferencia entre campos y propiedades, suponiendo que se puede acceder a los campos directamente sin obtener / establecer de una manera que sea idiomática para el lenguaje, y eso es permeable.

El objetivo de OOP es tratar las cosas como si fueran entidades en el mundo "real", no solo como estructuras con algún código mezclado. Otro programador debería necesitar saber muy, muy poco sobre la forma en que he implementado las cosas, y no debería preocuparse en absoluto con cuál de los diversos valores que se les permite obtener y / o establecer son reales y cuáles son virtuales. Si se encuentra con un vector mío, no debería necesitar saber si estoy almacenando ángulos y magnitudes o componentes reales e imaginarios internos del objeto vectorial. Si cambio la representación en V2.0 de mi biblioteca, no debería afectar su código en absoluto (aunque es posible que desee aprovechar las nuevas características interesantes). Del mismo modo, hay propiedades que una entidad podría tener que dependen de datos externos a la entidad, pero que sin duda son propiedades desde un punto de vista léxico. Le preguntas a la gente "cuántos años tienes", no "realiza el cálculo que me revelará tu edad", aunque sabes que los datos disponibles para ese "objeto" son la fecha de nacimiento (un miembro privado inmutable) y el de hoy fecha (una propiedad ambiental pública, de incremento automático, que depende de la zona horaria, el horario de verano y la línea de fecha internacional). La edad es una propiedad, no un método, a pesar de que se necesitan algunos cálculos para llegar allí y no se puede almacenar (como en las representaciones de la computadora de juguete de cosas con vidas limitadas artificialmente) como un campo. a pesar de que sabe que los datos disponibles para ese "objeto" son la fecha de nacimiento (un miembro inmutable privado) y la fecha de hoy (una propiedad ambiental pública que se incrementa automáticamente, que depende de la zona horaria, el horario de verano y la línea de fecha internacional ) La edad es una propiedad, no un método, a pesar de que se necesitan algunos cálculos para llegar allí y no se puede almacenar (como en las representaciones de la computadora de juguete de cosas con vidas limitadas artificialmente) como un campo. a pesar de que sabe que los datos disponibles para ese "objeto" son la fecha de nacimiento (un miembro inmutable privado) y la fecha de hoy (una propiedad ambiental pública que se incrementa automáticamente, que depende de la zona horaria, el horario de verano y la línea de fecha internacional ) La edad es una propiedad, no un método, a pesar de que se necesitan algunos cálculos para llegar allí y no se puede almacenar (como en las representaciones de la computadora de juguete de cosas con vidas limitadas artificialmente) como un campo.

En lugar de pensar en las propiedades como el hijo bastardo de los campos y métodos, es mucho más satisfactorio considerar a los métodos como un tipo especializado de propiedad, cosas que sus entidades pueden hacer en lugar de cosas que son. De lo contrario, no se trata conceptualmente de objetos / entidades, se trata de colecciones de datos que tienen un código adjunto. Las implementaciones pueden ser idénticas, pero las implicaciones son diferentes.

Sin embargo, debería ser innecesario decir que esta abstracción tiene un costo. Si un programador que usa una clase no puede determinar si está accediendo a los datos tal como están almacenados o si está obteniendo / estableciendo valores que deben calcularse, entonces habrá un nivel en el que el lenguaje también es necesariamente incierto (y, por lo tanto, puede requieren que todo requiera código para intermediar entre accesores / selectores y valores). No hay nada conceptualmente incorrecto con las "estructuras con código", sin duda pueden ser mucho más eficientes, pero filtran la implementación por todas partes, y esa es una de las cosas que se supone que debe eliminar OOP.


Estoy de acuerdo con algunos puntos y no estoy de acuerdo con otros, pero el mensaje general es bueno: es necesario calcular cierta información sobre un objeto, pero aún es técnicamente información que es más que una acción que se puede hacer .
Pharap

0

Absolutamente nada en absoluto. Las propiedades y OOP no tienen nada que ver entre sí. Las propiedades no son más que azúcar sintáctica para las llamadas a funciones y, por lo tanto, tienen exactamente el mismo archivo adjunto de OOP que las llamadas a funciones, es decir, ninguna.

Wikipedia es completamente incorrecta, por cierto. El patrón getMember / setMember que ve en Java ofrece exactamente las mismas ventajas (y desventajas) que las propiedades en C #. Y puede replicar este patrón incluso en C si lo desea.

Las propiedades en C # no son más que azúcar sintáctica compatible con el lenguaje.


3
¿Alguna vez has visto el concepto de propiedad en algún lenguaje de programación fuera de un contexto de clase u objeto? Yo no tengo.
Doc Brown

1
@DocBrown: lo he implementado. El hecho es que las propiedades son objetivos de poco valor para los autores de idiomas, ya que su mejora con respecto a las llamadas a funciones regulares es baja.
DeadMG

1
OP estaba preguntando sobre la historia de las propiedades como un concepto en lenguajes de programación populares. Y en realidad, en el sentido histórico, existe una conexión entre las propiedades y la OOP.
Doc Brown

2
Tal vez fui un poco imprudente al atribuir este concepto de propiedades al paradigma OOP per se, pero como concepto ciertamente trasciende los lenguajes individuales y sus características. Tal vez estoy luchando por articular la ontología apropiada entre los dos. No estoy sugiriendo a través del título de la pregunta que las propiedades son una característica / concepto fundamental de OOP que hace o rompe el formalismo OOP, y sin embargo, tengo la sensación de que solo tienen una realidad en este espacio OOP, por eso formulé la pregunta como tal .
jxramos

44
No son solo azúcar de sintaxis en C #, existen en los metadatos del ensamblaje como miembros distintos y puede hacer cosas con propiedades que no puede hacer con campos, como el enlace de datos.
Andy
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.