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.
BMI = bob.weight/sq(bob.height)
se lee mejor sin()
IMO.Respuestas:
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)
deshacerse de los métodos por completo, solo tener datos (Self hace esto, los "métodos" son solo
Method
objetos 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, porfoo.bar_=(baz)
ejemplo, llamar a un método llamadofoo_=
, y los valores de solo lectura pueden ser anulados o implementados por un método sin lista de parámetros (es decir,val foo
en una superclase puede ser anulado (oabstract
val
implementado) en una subclase con un métododef 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.bar
es diferente defoo.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.
fuente
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.
fuente
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
GetX
ySetX
emparejar 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.
fuente
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.
fuente
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:
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.
fuente
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.
fuente
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.
fuente