Articulo de referencia

Propiedad (programación)

En algunos lenguajes de programación orientados a objetos , una propiedad es un tipo especial de miembro de clase , con una funcionalidad intermedia entre un campo (o miembro de...

En algunos lenguajes de programación orientados a objetos , una propiedad es un tipo especial de miembro de clase , con una funcionalidad intermedia entre un campo (o miembro de datos) y un método . La sintaxis para leer y escribir propiedades es similar a la de los campos, pero las lecturas y escrituras de propiedades se traducen (generalmente) a llamadas a métodos " getter " y " setter ". Esta sintaxis, similar a la de los campos, facilita la lectura y escritura en comparación con muchas llamadas a métodos; sin embargo, la interposición de llamadas a métodos permite la validación de datos , la actualización activa (por ejemplo, de elementos de la interfaz gráfica de usuario , GUI) o la implementación de lo que se denomina " campos de solo lectura ".

Soporte en idiomas

Los lenguajes de programación que admiten propiedades incluyen C# , D , ECMAScript ( ActionScript 3 , JavaScript ), eC, F# , Kotlin , Object Pascal ( Delphi , Free Pascal ), Objective-C 2.0 , Python , Scala , Swift , Lua y Visual Basic .

Algunos lenguajes orientados a objetos, como Java y C++ , no admiten propiedades, lo que obliga al programador a definir un par de métodos de acceso y modificación . [ 1 ]

Oberon-2 proporciona un mecanismo alternativo que utiliza indicadores de visibilidad de variables de objeto.

Otros lenguajes diseñados para la máquina virtual de Java , como Groovy , admiten propiedades de forma nativa.

Aunque C++ no tiene propiedades de primera clase, estas pueden emularse mediante la sobrecarga de operadores . [ 2 ]

Algunos compiladores de C++ admiten propiedades de primera clase como extensiones del lenguaje.

En muchos lenguajes orientados a objetos, las propiedades se implementan como un par de métodos de acceso y modificación, pero se accede a ellas con la misma sintaxis que a los campos públicos. Si se omite un método del par, se obtiene una propiedad de solo lectura o, en raras ocasiones, de solo escritura .

En algunos lenguajes que no admiten propiedades de forma nativa, se puede implementar una estructura similar como un único método que devuelve o modifica los datos subyacentes, según el contexto de su invocación. Estas técnicas se utilizan, por ejemplo, en Perl .

Algunos lenguajes ( Ruby , Smalltalk ) logran una sintaxis similar a la de las propiedades utilizando métodos normales, a veces con una cantidad limitada de azúcar sintáctico .

Variantes de sintaxis

Algunos lenguajes siguen convenciones sintácticas bien establecidas para especificar y utilizar formalmente propiedades y métodos.

Entre estas convenciones:

  • notación de puntos
  • Notación entre corchetes

notación de puntos

El siguiente ejemplo muestra la notación de puntos en JavaScript.

documento.createElement ( "pre " ) ;

Notación entre corchetes

El siguiente ejemplo muestra la notación de corchetes en JavaScript.

documento [ "createElement" ]( "pre" );

Ejemplo de sintaxis

DO#

clase Pen { int privado color ; // campo privado // propiedad pública int Color { obtener { devolver este.color ; } establecer { si ( valor > 0 ) { este.color = valor ; } } } }
// acceso: Pen pen = new (); int colorTmp = 0 ; // ... pen . Color = 17 ; colorTmp = pen . Color ; // ... pen . Color = ~ pen . Color ; // complemento bit a bit ...// otro ejemplo tonto: pen . Color += 1 ; // ¡mucho más claro que "pen.set_Color(pen.get_Color() + 1)"!

Las versiones recientes de C# también permiten "propiedades de implementación automática", donde el compilador genera el campo subyacente de la propiedad durante la compilación. Esto significa que la propiedad debe tener un método setter. Sin embargo, puede ser privado.

clase Forma { public int Altura { obtener ; establecer ; } public int Ancho { obtener ; establecer ; } }

C++

C++ no tiene propiedades de primera clase, pero existen varias maneras de emularlas hasta cierto punto. Dos de ellas se describen a continuación:

Utilizando C++ estándar

importar std ;usando std :: same_as ;plantilla < typename T > clase Propiedad { T valor ; público : // Asegurar que T y T2 sean del mismo tipo plantilla < typename U > requiere same_as < T , U > T & operador = ( const U & i ) { valor = i ; devolver * this ; }// Conversión implícita de vuelta a T. operator T const & () const { return value ; } };struct Foo { // Propiedades que utilizan clases sin nombre. class { private : int value ; public : int & operator = ( const int & i ) { return value = i ; } int operator int () const { return value ; } } alpha ;clase { privado : float valor ; público : float & operador = ( const float & f ) { valor de retorno = f ; } float operador float () const { valor de retorno ; } } bravo ; };struct Bar { // Usando la plantilla Property<>. Propiedad < bool > alpha ; Propiedad < unsigned int > bravo ; };int main ( int argc , char * argv []) { Foo foo ; foo . alpha = 5 ; foo . bravo = 5.132f ;Bar bar ; bar.alpha = true ; bar.bravo = true ; // Esta línea generará un error de compilación debido a la función miembro de la plantilla guard. std :: println ( " { } , { } , { }, { } " , foo.alpha , foo.bravo , bar.alpha , bar.bravo ) ; return 0 ; }

C++, Microsoft, GCC, LLVM/clang y C++Builder específicos

Un ejemplo adaptado de la página de documentación de MSDN .

// declspec_property.cpp struct Integer { int value ;void setValue ( int j ) noexcept { valor = j ; }[[ nodiscard ]] int getValue () const noexcept { return i ; }__declspec ( propiedad ( obtener = obtenerValor , poner = establecerValor )) int prop ; };int main ( ) { Integer s ; s.prop = 5 ; return 0 ; }

D

clase Pen { private int myColor ; // campo privado // propiedad pública get public int color () { return myColor ; } // propiedad pública set public void color ( int value ) { myColor = value ; } }
Pen pen = new Pen ; pen.color = ~ pen.color ; // complemento bit a bit// La propiedad set también se puede usar en expresiones, al igual que una asignación normal int theColor = ( pen . color = 0xFF0000 );

En la versión 2 de D, cada accesor o modificador de propiedad debe estar marcado con @property:

clase Pen { private int myColor ; // campo privado // propiedad pública get @property public int color () { return myColor ; } // propiedad pública set @property public void color ( int value ) { myColor = value ; } }

CE

clase Bolígrafo { // miembro de datos privado Color color ; público : // propiedad pública propiedad Color color { obtener { devolver color ; } establecer { color = valor ; } } } Bolígrafo negro { color = negro }; Bolígrafo blanco { color = blanco }; Bolígrafo bolígrafo3 { color = { 30 , 80 , 120 } }; Bolígrafo bolígrafo4 { color = ColorHSV { 90 , 20 , 40 } };

F#

tipo Pen () = clase let mutable _ color = 0miembro este . Color con obtener () = _ color y establecer valor = _ color <- valor fin
let pen = new Pen () pen . Color <- ~~~ pen . Color

JavaScript

function Pen () { this . _color = 0 ; } // Agrega la propiedad al tipo Pen en sí, también se puede // establecer en la instancia individualmente Object . defineProperties ( Pen . prototype , { color : { get : function () { return this . _color ; }, set : function ( value ) { this . _color = value ; } } });
var pen = new Pen (); pen . color = ~ pen . color ; // complemento bit a bit pen . color += 1 ; // Sumar uno

ActionScript 3.0

paquete { clase pública Pen { variable privada _color : uint = 0 ; función pública obtener color (): uint { return _color ; } función pública establecer color ( valor : uint ): void { _color = valor ; } } }
var pen : Pen = new Pen (); pen.color = ~ pen.color ; // complemento bit a bit pen.color + = 1 ; // sumar uno

Object Pascal (Delphi, Free Pascal)

tipo TPen = clase privada FColor : TColor ; función GetColor : TColor ; procedimiento SetColor ( const AValue : TColor ) ; propiedad pública Color : Integer leer GetColor escribir SetColor ; fin ;función TPen . GetColor : TColor ; inicio Resultado := FColor ; fin ;procedimiento TPen . EstablecerColor ( const AValue : TColor ) ; comience si FColor <> AValue entonces FColor := AValue ; fin ;
// acceso: var Pen : TPen ; // ... Pen . Color := not Pen . Color ;(* Delphi y Free Pascal también admiten una sintaxis de 'campo directo' -propiedad Color: TColor leer FColor escribir SetColor;opropiedad Color: TColor leer GetColor escribir FColor;donde el compilador genera exactamente el mismo código que para leer y escribir un campo. Esto ofrece la eficiencia de un campo con la seguridad de una propiedad. (Un puntero no puede acceder a la propiedad, y el acceso a un miembro siempre se puede reemplazar con una llamada a un método) .

Objective-C 2.0

@interface Pen : NSObject @property ( copy ) NSColor * color ; // El atributo "copy" hace que se conserve la copia del objeto , // en lugar del original. @end@implementation Pen @synthesize color ; // Directiva del compilador para sintetizar métodos de acceso. // Se puede dejar atrás en Xcode 4.5 y versiones posteriores. @end

El ejemplo anterior podría utilizarse en un método arbitrario como este:

Pluma * pluma = [[ Pluma alloc ] init ]; pluma . color = [ NSColor blackColor ]; float rojo = pluma . color . componente rojo ; [ pluma . color drawSwatchInRect : NSMakeRect ( 0 , 0 , 100 , 100 )];

PHP

clase Pen { int privado $color = 1 ;function __set ( $property , $value ) { if ( property_exists ( $this , $property )) { $this -> $property = $value ; } }function __get ( $property ) { if ( property_exists ( $this , $property )) { return $this -> $property ; } return null ; } }
$p = new Pen (); $p -> color = ~ $p -> color ; // Complemento bit a bit echo $p -> color ;

Pitón

Las propiedades solo funcionan correctamente para las clases de nuevo estilo (clases que tienen objectcomo superclase ), y solo están disponibles en Python 2.2 y versiones posteriores (consulte la sección correspondiente del tutorial Unificación de tipos y clases en Python 2.2 ). Python 2.6 añadió una nueva sintaxis que utiliza decoradores para definir propiedades.

clase Pen : _color : int # variable "privada"def __init__ ( self ) -> None : self . _color = 0@property def color ( self ) -> int : return self . _color@color . setter def color ( self , color : int ) -> None : self . _color = color
bolígrafo : Bolígrafo = Bolígrafo () # Acceso: bolígrafo.color = ~ bolígrafo.color # Complemento bit a bit ...

Rubí

clase Pen def inicializar @color = 0 end # Define un método getter para el campo @color def color @color end# Define un método setter para el campo @color def color = ( valor ) @color = valor end endbolígrafo = Bolígrafo.nuevo bolígrafo.color = ~ bolígrafo.color # Complemento bit a bit

Ruby también proporciona sintetizadores automáticos de getter/setter definidos como métodos de instancia de Class.

clase Pen attr_reader :brand # Genera un getter para @brand (solo lectura) attr_writer :size # Genera un setter para @size (solo escritura) attr_accessor :color # Genera un getter y un setter para @color (lectura/escritura)def initialize @color = 0 # Dentro del objeto, podemos acceder a la variable de instancia directamente @brand = "Penbrand" @size = 0 . 7 # Pero también podríamos usar el método setter definido por el método de instancia de la clase attr_accessor end endbolígrafo = Bolígrafo.nuevo pone bolígrafo.marca # Accede a la marca del bolígrafo a través del getter generado bolígrafo.tamaño = 0.5 # Actualiza el campo tamaño del bolígrafo a través del setter generado bolígrafo.color = ~ bolígrafo.color

Visual Basic

Visual Basic (.NET 2003–2010)

Clase pública Pluma Privada _color Como Entero ' Campo privadoPropiedad pública Color () Como entero ' Propiedad pública Obtener Devolver _color Fin Obtener Establecer ( Por valor valor Como entero ) _color = valor Fin Establecer Fin PropiedadFin de clase
' Crear una instancia de la clase Pen Dim pen As New Pen ()' Establecer valor del bolígrafo . Color = 1' Obtener valor Dim color As Int32 = pen . Color

Visual Basic (solo .NET 2010)

Pen de clase públicaColor de propiedad pública () como entero ' Propiedad públicaFin de clase
' Crear una instancia de la clase Pen Dim pen As New Pen ()' Establecer valor del bolígrafo . Color = 1' Obtener valor Dim color As Int32 = pen . Color

Visual Basic 6

' en una clase llamada clsPen Private m_Color As LongPropiedad pública Obtener color () Como Color = m_Color Fin de la propiedadPropiedad pública Let Color ( ByVal RHS As Long ) m_Color = RHS Fin de la propiedad
' accediendo: Dim pen As New clsPen ' ... pen . Color = Not pen . Color

Véase también

Referencias

  1. "Accesores y mutadores en Java" . C# Corner - Comunidad de desarrolladores de software y datos . Consultado el 5 de enero de 2022 .
  2. "Portabilidad de las propiedades nativas de C++" . Stack Overflow . Stack Overflow . Consultado el 5 de enero de 2022 .
  3. "propiedad (C++)" . Documentación técnica de Microsoft . Microsoft . Consultado el 5 de enero de 2022 .
  4. "clang::MSPropertyDecl Class Reference" . Clang: una interfaz para la familia de lenguajes C de LLVM . Consultado el 5 de enero de 2022 .
  5. "__property Keyword Extension" . Wiki de documentación de Embarcadero/IDERA . Consultado el 5 de enero de 2022 .