Property (programming)

{{short description|Sort of class member in programming languages}}

{{more citations needed|date=January 2022}}

A property, in some object-oriented programming languages, is a special sort of class member, intermediate in functionality between a field (or data member) and a method. The syntax for reading and writing of properties is like for fields, but property reads and writes are (usually) translated to 'getter' and 'setter' method calls. The field-like syntax is easier to read and write than many method calls,{{citation needed|date=March 2020}} yet the interposition of method calls "under the hood" allows for data validation, active updating (e.g., of GUI elements), or implementation of what may be called "read-only fields".

Support in languages

Programming languages that support properties include ActionScript 3, C#, D, Delphi/Free Pascal, eC, F#, Kotlin, JavaScript, Objective-C 2.0, Python, Scala, Swift, Lua, and Visual Basic.

Some object-oriented languages, such as Java and C++, do not support properties, requiring the programmer to define a pair of accessor and mutator methods instead.{{cite web |title=Accessors And Mutators In Java |url=https://www.c-sharpcorner.com/UploadFile/3614a6/accessors-and-mutators-in-java/ |website=C# Corner - Community of Software and Data Developers |access-date=5 January 2022}}{{citation needed|date=March 2020}}

Oberon-2 provides an alternative mechanism using object variable visibility flags.{{citation needed|date=March 2020}}

Other languages designed for the Java Virtual Machine, such as Groovy, natively support properties.

While C++ does not have first class properties, they can be emulated with operator overloading.{{cite web |title=Portability of Native C++ properties |url=https://stackoverflow.com/questions/5772480/portability-of-native-c-properties |website=Stack Overflow |publisher=Stack Overflow |access-date=5 January 2022}}

Also note that some C++ compilers support first class properties as language extensions.{{citation needed|date=March 2020}}

  • In Microsoft Visual Studio,{{cite web |title=property (C++) |url=https://docs.microsoft.com/en-us/cpp/cpp/property-cpp?view=msvc-170 |website=Microsoft technical documentation |publisher=Microsoft |access-date=5 January 2022 |ref=21 November 2021}} GCC, and llvm/clang,{{cite web |title=clang::MSPropertyDecl Class Reference |url=https://clang.llvm.org/doxygen/classclang_1_1MSPropertyDecl.html |website=Clang: a C language family frontend for LLVM |access-date=5 January 2022}} the __declspec(property) creates properties similar to C#.
  • Borland C++ and Borland/CodeGear/Embarcadero C++Builder use the __property keyword.{{cite web |title=__property Keyword Extension |url=https://docwiki.embarcadero.com/RADStudio/Sydney/en/Property |website=Embarcadero/IDERA Documentation Wiki |access-date=5 January 2022}}

In many object oriented languages properties are implemented as a pair of accessor/mutator methods, but accessed using the same syntax as for public fields. Omitting a method from the pair yields a read-only or an uncommon write-only property.

In some languages with no built-in support for properties, a similar construct can be implemented as a single method that either returns or changes the underlying data, depending on the context of its invocation. Such techniques are used e.g. in Perl. {{citation needed|date=March 2020}}

Some languages (Ruby, Smalltalk) achieve property-like syntax using normal methods, sometimes with a limited amount of syntactic sugar.

Syntax variants

Some languages follow well-established syntax conventions for formally specifying and utilizing properties and methods.

Among these conventions:

  • Dot notation
  • Bracket notation

= Dot notation =

The following example demonstrates dot notation in JavaScript.

document.createElement('pre');

= Bracket notation =

The following example demonstrates bracket notation in JavaScript.

document['createElement']('pre');

Example syntax

= C# =

class Pen

{

private int color; // private field

// public property

public int Color

{

get

{

return this.color;

}

set

{

if (value > 0) {

this.color = value;

}

}

}

}

// accessing:

Pen pen = new Pen();

int color_tmp = 0;

// ...

pen.Color = 17;

color_tmp = pen.Color;

// ...

pen.Color = ~pen.Color; // bitwise complement ...

// another silly example:

pen.Color += 1; // a lot clearer than "pen.set_Color(pen.get_Color() + 1)"!

Recent C# versions also allow "auto-implemented properties" where the backing field for the property is generated by the compiler during compilation. This means that the property must have a setter. However, it can be private.

class Shape

{

public int Height { get; set; }

public int Width { get; private set; }

}

= C++ =

{{unreferenced section|date=October 2016}}

{{confusing|date=October 2016}}

C++ does not have first class properties, but there exist several ways to emulate properties to a limited degree. Two of which follow:

== Using Standard C++ ==

  1. include

template class property {

T value;

public:

T & operator = (const T &i) {

return value = i;

}

// This template class member function template serves the purpose to make

// typing more strict. Assignment to this is only possible with exact identical types.

// The reason why it will cause an error is temporary variable created while implicit type conversion in reference initialization.

template T2 & operator = (const T2 &i) {

T2 &guard = value;

throw guard; // Never reached.

}

// Implicit conversion back to T.

operator T const & () const {

return value;

}

};

struct Foo {

// Properties using unnamed classes.

class {

int value;

public:

int & operator = (const int &i) { return value = i; }

operator int () const { return value; }

} alpha;

class {

float value;

public:

float & operator = (const float &f) { return value = f; }

operator float () const { return value; }

} bravo;

};

struct Bar {

// Using the property<>-template.

property alpha;

property bravo;

};

int main () {

Foo foo;

foo.alpha = 5;

foo.bravo = 5.132f;

Bar bar;

bar.alpha = true;

bar.bravo = true; // This line will yield a compile time error

// due to the guard template member function.

::std::cout << foo.alpha << ", "

<< foo.bravo << ", "

<< bar.alpha << ", "

<< bar.bravo

<< ::std::endl;

return 0;

}

Also see [https://stackoverflow.com/a/5924594 Stack Overflow] for a more detailed example.

== C++, Microsoft, GCC, LLVM/clang and C++Builder-specific ==

An example taken from the MSDN [http://msdn.microsoft.com/en-us/library/yhfk0thd.aspx documentation page].

// declspec_property.cpp

struct S

{

int i;

void putprop(int j)

{

i = j;

}

int getprop()

{

return i;

}

__declspec(property(get = getprop, put = putprop)) int the_prop;

};

int main()

{

S s;

s.the_prop = 5;

return s.the_prop;

}

= D =

class Pen

{

private int m_color; // private field

// public get property

public int color () {

return m_color;

}

// public set property

public void color (int value) {

m_color = value;

}

}

auto pen = new Pen;

pen.color = ~pen.color; // bitwise complement

// the set property can also be used in expressions, just like regular assignment

int theColor = (pen.color = 0xFF0000);

In D version 2, each property accessor or mutator must be marked with @property:

class Pen

{

private int m_color; // private field

// public get property

@property public int color () {

return m_color;

}

// public set property

@property public void color (int value) {

m_color = value;

}

}

= Delphi/Free Pascal =

type TPen = class

private

FColor: TColor;

function GetColor: TColor;

procedure SetColor(const AValue: TColor);

public

property Color: Integer read GetColor write SetColor;

end;

function TPen.GetColor: TColor;

begin

Result := FColor;

end;

procedure TPen.SetColor(const AValue: TColor);

begin

if FColor <> AValue

then FColor := AValue;

end;

// accessing:

var Pen: TPen;

// ...

Pen.Color := not Pen.Color;

(*

Delphi and Free Pascal also support a 'direct field' syntax -

property Color: TColor read FColor write SetColor;

or

property Color: TColor read GetColor write FColor;

where the compiler generates the exact same code as for reading and writing

a field. This offers the efficiency of a field, with the safety of a property.

(You can't get a pointer to the property, and you can always replace the member

access with a method call.)

  • )

= eC =

class Pen

{

// private data member

Color color;

public:

// public property

property Color color

{

get { return color; }

set { color = value; }

}

}

Pen blackPen { color = black };

Pen whitePen { color = white };

Pen pen3 { color = { 30, 80, 120 } };

Pen pen4 { color = ColorHSV { 90, 20, 40 } };

= F# =

type Pen() = class

let mutable _color = 0

member this.Color

with get() = _color

and set value = _color <- value

end

let pen = new Pen()

pen.Color <- ~~~pen.Color

= JavaScript =

function Pen() {

this._color = 0;

}

// Add the property to the Pen type itself, can also

// be set on the instance individually

Object.defineProperties(Pen.prototype, {

color: {

get: function () {

return this._color;

},

set: function (value) {

this._color = value;

}

}

});

var pen = new Pen();

pen.color = ~pen.color; // bitwise complement

pen.color += 1; // Add one

= ActionScript 3.0 =

package {

public class Pen {

private var _color:uint = 0;

public function get color ():uint {

return _color;

}

public function set color(value:uint):void {

_color = value;

}

}

}

var pen:Pen = new Pen();

pen.color = ~pen.color; // bitwise complement

pen.color += 1; // add one

= Objective-C 2.0 =

@interface Pen : NSObject

@property (copy) NSColor *colour; // The "copy" attribute causes the object's copy to be

// retained, instead of the original.

@end

@implementation Pen

@synthesize colour; // Compiler directive to synthesise accessor methods.

// It can be left behind in Xcode 4.5 and later.

@end

The above example could be used in an arbitrary method like this:

Pen *pen = [[Pen alloc] init];

pen.colour = [NSColor blackColor];

float red = pen.colour.redComponent;

[pen.colour drawSwatchInRect: NSMakeRect(0, 0, 100, 100)];

= PHP =

class Pen

{

private int $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; // Bitwise complement

echo $p->color;

= Python =

Properties only work correctly for new-style classes (classes that have object as a superclass), and are only available in Python 2.2 and newer (see [https://www.python.org/download/releases/2.2/descrintro/#property the relevant section of the tutorial Unifying types and classes in Python 2.2]). Python 2.6 added a new syntax involving decorators for defining properties.

class Pen:

def __init__(self) -> None:

self._color = 0 # "private" variable

@property

def color(self):

return self._color

@color.setter

def color(self, color):

self._color = color

pen = Pen()

  1. Accessing:

pen.color = ~pen.color # Bitwise complement ...

= Ruby =

class Pen

def initialize

@color = 0

end

# Defines a getter for the @color field

def color

@color

end

# Defines a setter for the @color field

def color=(value)

@color = value

end

end

pen = Pen.new

pen.color = ~pen.color # Bitwise complement

Ruby also provides automatic getter/setter synthesizers defined as instance methods of Class.

class Pen

attr_reader :brand # Generates a getter for @brand (Read-Only)

attr_writer :size # Generates a setter for @size (Write-Only)

attr_accessor :color # Generates both a getter and setter for @color (Read/Write)

def initialize

@color = 0 # Within the object, we can access the instance variable directly

@brand = "Penbrand"

@size = 0.7 # But we could also use the setter method defined by the attr_accessor Class instance method

end

end

pen = Pen.new

puts pen.brand # Accesses the pen brand through the generated getter

pen.size = 0.5 # Updates the size field of the pen through the generated setter

pen.color = ~pen.color

= Visual Basic =

== Visual Basic (.NET 2003–2010) ==

Public Class Pen

Private _color As Integer ' Private field

Public Property Color() As Integer ' Public property

Get

Return _color

End Get

Set(ByVal value As Integer)

_color = value

End Set

End Property

End Class

' Create Pen class instance

Dim pen As New Pen()

' Set value

pen.Color = 1

' Get value

Dim color As Int32 = pen.Color

== Visual Basic (only .NET 2010) ==

Public Class Pen

Public Property Color() As Integer ' Public property

End Class

' Create Pen class instance

Dim pen As New Pen()

' Set value

pen.Color = 1

' Get value

Dim color As Int32 = pen.Color

== Visual Basic 6 ==

' in a class named clsPen

Private m_Color As Long

Public Property Get Color() As Long

Color = m_Color

End Property

Public Property Let Color(ByVal RHS As Long)

m_Color = RHS

End Property

' accessing:

Dim pen As New clsPen

' ...

pen.Color = Not pen.Color

See also

References