Property (programming)
≈ 8 min read
Names in other languages
No names in other languages are held for this entry yet.
Article bodies are English and are not machine-translated. A name in another language is not a translation of the article.
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, yet the interposition of method calls "under the hood" allows for data validation, active updating (e.g., of graphical user interface (GUI) elements), or implementing what may be called "read-only fields".
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, yet the interposition of method calls "under the hood" allows for data validation, active updating (e.g., of graphical user interface (GUI) elements), or implementing what may be called "read-only fields". document.createElement("pre"); document["createElement"]("pre"); 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(); int colorTmp = 0; // ... pen.Color = 17; colorTmp = 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; } } struct Foo { class { private: int value; public: int& operator=(const int& i) { return value = i; } int operator int() const { return value; } } alpha; class { private: float value; public: float& operator=(const float& f) { return value = f; } float operator float() const { return value; } } bravo; }; Additionally, a dedicated, reusable Property type with support for custom assignment and retrieval could look like this: import std; using std::conditional_t; using std::convertible_to; using std::function; using std::monostate; // WithMutator and WithAccessor determine whether mutators and accessors are generated template , monostate >, typename AccessorFunc = conditional_t , monostate > > class Property { private: T value; no_unique_address MutatorFunc mutator; no_unique_address AccessorFunc accessor; public: Property(const T& x = {}) requires (!WithMutator && !WithAccessor): value{x} {} Property(const T& x = {}, MutatorFunc m = {}, AccessorFunc a = {}) requires (WithMutator || WithAccessor): value{x}, mutator{m}, accessor{a} {} // Assignment operator with implicit conversion // Generated only when WithMutator = true Property& operator=(convertible_to auto const& x) requires (WithMutator) { if (mutator) { mutator(value, x); } else { value = x; } return *this; } // Implicit conversion back to T. // Generated only when WithAccessor = true nodiscard operator T const&() const requires (WithAccessor) { if (accessor) { return accessor(value); } return value; } }; namespace std { template struct formatter > : public formatter { auto format(const Property & prop, format_context& ctx) const { const T& value = static_cast (prop); return formatter ::format(value, ctx); } }; } struct Foo { // all Property fields must be public Property alpha; Property bravo; }; int main(int argc, char* argv[]) { Foo foo; foo.alpha = true; foo.bravo = 1; std::println("{}, {}, {}, {}", foo.alpha, foo.bravo); return 0; } // declspec_property.cpp struct Integer { int value; void setValue(int j) noexcept { value = j; } nodiscard int getValue() const noexcept { return i; } __declspec(property(get = getValue, put = setValue)) int prop; }; int main() { Integer s; s.prop = 5; return 0; } class Pen { private int myColor; // private field // public get property public int color() { return myColor; } // public set property public void color(int value) { myColor = value; } } Pen 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 myColor; // private field // public get property @property public int color() { return myColor; } // public set property @property public void color(int value) { myColor = value; } } 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 } }; type Pen() = class let mutable _color = 0 member this.Color with get() = _color and set value = _color let pen = new Pen() pen.Color 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; } } }); let pen = new Pen(); pen.color = ~pen.color; // bitwise complement pen.color += 1; // Add one 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 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. (A pointer cannot get to the property, and a member access can always be replaced with a method call.) ) @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)]; 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; class Pen: _color: int # "private" variable 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 pen: Pen = Pen() Accessing: pen.color = ~pen.color # Bitwise complement ... 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 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 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 ' 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 ==References==
Text derived from https://en.wikipedia.org/w/index.php?oldid=1378798789 under CC BY-SA 4.0; modifications have been made.