Una propiedad , en algunos lenguajes de programación orientados a objetos , es un tipo especial de miembro de clase , de funcionalidad intermedia entre un campo (o miembro de datos) y un método . La sintaxis para la lectura y escritura de propiedades es como la de los campos, pero las lecturas y escrituras de propiedades se traducen (normalmente) a llamadas de método ' getter ' y ' setter '. La sintaxis similar a un campo es más fácil de leer y escribir que muchas llamadas a métodos [ cita requerida ] , sin embargo, la interposición de llamadas a métodos "bajo el capó" permite la validación de datos , la actualización activa (por ejemplo, deElementos de la GUI ), o la implementación de lo que se puede llamar " campos de sólo lectura ".
Vea un ejemplo instructivo para el lenguaje C # a continuación.
Soporte en idiomas
Los lenguajes de programación que admiten propiedades incluyen ActionScript 3 , C # , D , Delphi / Free Pascal , eC , F # , Kotlin , JavaScript , Objective-C 2.0 , Python , Scala , Swift , Lua y Visual Basic .
Algunos lenguajes orientados a objetos, como Java y C ++ , no admiten propiedades y requieren que el programador defina un par de métodos de acceso y mutador en su lugar. [ cita requerida ]
Oberon-2 proporciona un mecanismo alternativo que utiliza indicadores de visibilidad de variables de objeto. [ cita requerida ]
Otros lenguajes diseñados para la máquina virtual Java , como Groovy , admiten propiedades de forma nativa.
Si bien C ++ no tiene propiedades de primera clase, se pueden emular debido a la sobrecarga del operador .
También tenga en cuenta que algunos compiladores de C ++ admiten propiedades de primera clase (el compilador de Microsoft C ++ como ejemplo). [ cita requerida ]
En la mayoría de los lenguajes, las propiedades se implementan como un par de métodos de acceso / mutador, pero se accede utilizando la misma sintaxis que para los campos públicos. Omitir un método del par produce una propiedad de solo lectura o una propiedad de solo escritura poco común .
En algunos lenguajes sin soporte integrado para propiedades, se puede implementar una construcción similar como un método único que devuelve o cambia los datos subyacentes, según el contexto de su invocación. Tales técnicas se utilizan, por ejemplo, en Perl . [ cita requerida ]
Algunos lenguajes (Ruby, Smalltalk) logran una sintaxis similar a una propiedad usando métodos normales, a veces con una cantidad limitada de azúcar sintáctico .
Variantes de sintaxis
Algunos lenguajes siguen convenciones de sintaxis bien establecidas para especificar y utilizar propiedades y métodos formalmente.
Entre estas convenciones:
- Notación de puntos
- Notación de corchetes
Notación de puntos
El siguiente ejemplo demuestra la notación de puntos en JavaScript.
documento . createElement ( 'pre' );
Notación de corchetes
El siguiente ejemplo demuestra la notación entre corchetes en JavaScript.
documento [ 'createElement' ] ( 'pre' );
Sintaxis de ejemplo
C#
class Pen { color privado int ; // campo privado // propiedad pública public int Color { get { return this . el color ; } establecer { si ( valor > 0 ) { esto . color = valor ; } } } }
// accediendo a: Pen pen = new Pen (); int color_tmp = 0 ; // ... bolígrafo . Color = 17 ; color_tmp = bolígrafo . Color ; // ... bolígrafo . Color = ~ bolígrafo . Color ; // complemento bit a bit ...// otro ejemplo tonto: bolígrafo . Color + = 1 ; // ¡mucho más claro que "pen.set_Color (pen.get_Color () + 1)"!
Las versiones recientes de C # también permiten "propiedades implementadas automáticamente" donde el compilador genera el campo de respaldo para la propiedad durante la compilación. Esto significa que la propiedad debe tener un setter. Sin embargo, puede ser privado.
class Shape { altura pública Int32 { get ; establecer ; } Pública Int32 Ancho { get ; conjunto privado ; } }
C ++
C ++ no tiene propiedades de primera clase, pero existen varias formas de emular propiedades hasta cierto punto. Dos de los cuales siguen:
#include plantilla < typename T > propiedad de clase { valor T ; public : T & operator = ( const T & i ) { valor de retorno = i ; } // Esta plantilla de función de miembro de clase de plantilla tiene el propósito de // hacer que la escritura sea más estricta. La asignación a esto solo es posible con tipos idénticos exactos. // La razón por la que causará un error es una variable temporal creada mientras se realiza una conversión de tipo implícita en la inicialización de referencia. plantilla < typename T2 > T2 & operator = ( const T2 & i ) { T2 & guard = value ; lanzar guardia ; // Nunca alcanzado. } // Conversión implícita de nuevo a T. operador T const & () const { valor de retorno ; } }; struct Foo { // Propiedades usando clases sin nombre. clase { valor int ; public : int & operator = ( const int & i ) { valor de retorno = i ; } operador int () const { valor de retorno ; } } alfa ; class { valor flotante ; public : float & operator = ( const float & f ) { valor de retorno = f ; } operator float () const { valor de retorno ; } } bravo ; }; struct Bar { // Usando la propiedad <> - plantilla. propiedad < bool > alpha ; propiedad < unsigned int > bravo ; };int main () { Foo foo ; foo . alfa = 5 ; foo . bravo = 5.132f ; Barra de bar ; bar . alfa = verdadero ; bar . bravo = verdadero ; // Esta línea producirá un error de tiempo de compilación // debido a la función del miembro de la plantilla de guardia. :: std :: cout << foo . alpha << "," << foo . bravo << "," << barra . barra alfa << "," << . bravo << :: std :: endl ; return 0 ; }
Específico para C ++, Microsoft y C ++ Builder
Un ejemplo tomado de la página de documentación de MSDN .
// declspec_property.cpp struct S { int i ; putprop vacío ( int j ) { i = j ; } int getprop () { retorno i ; } __declspec ( propiedad ( get = getprop , put = putprop )) int the_prop ; };int main () { S s ; s . the_prop = 5 ; volver s . the_prop ; }
D
class Pen { privado int m_color ; // campo privado // public obtener propiedad public int color () { return m_color ; } // public set propiedad public void color ( int value ) { m_color = value ; } }
auto pluma = nuevo Pen ; bolígrafo . color = ~ bolígrafo . el color ; // complemento bit a bit// la propiedad set también se puede usar en expresiones, al igual que la asignación regular int theColor = ( pen . color = 0xFF0000 );
En la versión 2 de D, cada descriptor de acceso o mutador de propiedad debe estar marcado con @property:
class Pen { privado int m_color ; // campo privado // public obtener propiedad @property public int color () { return m_color ; } // propiedad pública del conjunto @propiedad public void color ( valor int ) { m_color = valor ; } }
Delphi / Free Pascal
tipo TPen = clase privada FColor : TColor ; función GetColor : TColor ; procedimiento SetColor ( const AValue : TColor ) ; propiedad pública Color : Entero leído GetColor write SetColor ; terminar ; función TPen . GetColor : TColor ; comenzar Resultado : = FColor ; terminar ;procedimiento TPen . SetColor ( const AValue : TColor ) ; comenzar si FColor <> AValue luego FColor : = AValue ; terminar ;
// accediendo a: var Pen : TPen ; // ... Pluma . Color : = no bolígrafo . Color ;(* Delphi también admite 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. (No puede obtener un puntero a la propiedad y siempre puede reemplazar el acceso del miembro con una llamada al método). *)
CE
class Pen { // miembro de datos privados Color color ; public : // propiedad de propiedad pública Color color { get { return color ; } establecer { color = valor ; } } } Pen blackPen { color = black }; Bolígrafo whitePen { color = white }; Pen pen3 { color = { 30 , 80 , 120 } }; Pen pen4 { color = ColorHSV { 90 , 20 , 40 } };
F#
type Pen () = class let mutable _ color = 0 miembro de esto . Color con get () = _ color y valor establecido = _ color <- valor final
let pen = new Pen () pen . Color <- ~~~ bolígrafo . Color
JavaScript
función Pen () { esto . _color = 0 ; } // Agregue la propiedad al tipo de Pen en sí, también // se puede configurar en la instancia individualmente Object . defineProperties ( Pen . prototype , { color : { get : function () { return this . _color ; }, set : function ( value ) { this . _color = value ; } } });
var pen = new Pen (); bolígrafo . color = ~ bolígrafo . el color ; // Pluma de complemento bit a bit . color + = 1 ; // Agrega uno
ActionScript 3.0
paquete { público de clase Pen { privado var _Color : uint = 0 ; función pública get color (): uint { return _color ; } color del conjunto de funciones públicas ( valor : uint ): void { _color = valor ; } } }
var pen : Pen = new Pen (); bolígrafo . color = ~ bolígrafo . el color ; // Pluma de complemento bit a bit . color + = 1 ; // Agrega uno
Objective-C 2.0
@interface Pen : NSObject @property ( copia ) NSColor * color ; // El atributo "copiar" hace que se retenga la copia del objeto, // en lugar del original. @final@implementation Pen @synthesize color ; // Directiva del compilador para sintetizar los métodos de acceso. // Se puede dejar atrás en Xcode 4.5 y posteriores. @final
El ejemplo anterior podría usarse en un método arbitrario como este:
Pen * pen = [[ Pen alloc ] init ]; bolígrafo . color = [ NSColor blackColor ]; flotador rojo = bolígrafo . color . redComponent ; [ bolígrafo . color drawSwatchInRect : NSMakeRect ( 0 , 0 , 100 , 100 )];
PHP
class Pen { privado int $ color = 1 ; function __set ( $ propiedad , $ valor ) { si ( propiedad_existe ( $ esto , $ propiedad )) { $ esto -> $ propiedad = $ valor ; } } function __get ( $ propiedad ) { if ( property_exists ( $ this , $ property )) { return $ this -> $ propiedad ; } devolver nulo ; } }
$ p = nuevo lápiz (); $ p -> color = ~ $ p -> color ; // Complemento bit a bit echo $ p -> color ;
Pitón
Las propiedades solo funcionan correctamente para las clases de estilo nuevo (clases que tienen object
como superclase ), y solo están disponibles en Python 2.2 y versiones posteriores (consulte la sección correspondiente del tutorial Unificando tipos y clases en Python 2.2 ). Python 2.6 agregó una nueva sintaxis que involucra decoradores para definir propiedades.
clase Pluma : def __init__ ( self ) -> None : self . _color = 0 # variable "privada" @property def color ( self ): return self . _color @color . setter def color ( self , color ): self . _color = color
pen = Pen () # Accediendo: pen . color = ~ bolígrafo . color # Complemento bit a bit ...
Rubí
class Pen def initialize @color = 0 end # Define un captador para el campo @color def color @color end # Define un setter para el campo @color def color = ( value ) @color = value end endbolígrafo = bolígrafo . bolígrafo nuevo . color = ~ bolígrafo . color # complemento bit a bit
Ruby también proporciona sintetizadores getter / setter automáticos definidos como métodos de instancia de Class.
class Pen attr_reader : brand # Genera un captador para @brand (solo lectura ) attr_writer : size # Genera un configurador para @size (solo escritura ) attr_accessor : color # Genera tanto un captador como un configurador 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 clase attr_accessor end endbolígrafo = bolígrafo . nuevo pone bolígrafo . brand # Accede a la marca del bolígrafo a través del bolígrafo getter generado . tamaño = 0 . 5 # Actualiza el campo de tamaño de la pluma a través de la pluma de incubadora generada . color = ~ bolígrafo . color
Visual Basic
Visual Basic (.NET 2003-2010)
Bolígrafo de clase pública Private _color As Integer 'Campo privado Propiedad pública Color () As Integer 'Propiedad pública Get Return _color End Get Set ( valor ByVal como Integer ) _color = value End Set End Propiedad Clase final
'Crear instancia de clase Pluma Dim pen como nueva pluma ()'Establezca el valor de la pluma . Color = 1'Obtener valor Atenuar color como Int32 = pluma . Color
Visual Basic (solo .NET 2010)
Bolígrafo de clase pública Color de propiedad pública () As Integer 'Propiedad pública Clase final
'Crear instancia de clase Pluma Dim pen como nueva pluma ()'Establezca el valor de la pluma . Color = 1'Obtener valor Atenuar color como Int32 = pluma . Color
Visual Basic 6
'en una clase llamada clsPen Private m_Color As Long Propiedad pública Obtener color () como color largo = m_Color Propiedad final Propiedad pública Let Color ( ByVal RHS As Long ) m_Color = RHS End Property
'accediendo: Dim pen As New clsPen ' ... pen . Color = No bolígrafo . Color