In einigen objektorientierten Programmiersprachen ist eine Eigenschaft eine spezielle Art von Klassenmember , deren Funktionalität zwischen einem Feld (oder Datenmember) und einer Methode liegt . Die Syntax zum Lesen und Schreiben von Eigenschaften ähnelt der von Feldern, jedoch werden Lese- und Schreibzugriffe auf Eigenschaften (üblicherweise) in Getter- und Setter -Methodenaufrufe übersetzt. Die feldähnliche Syntax ist leichter lesbar und schreibbar als viele Methodenaufrufe. Die intern verwendeten Methodenaufrufe ermöglichen jedoch die Datenvalidierung , die aktive Aktualisierung (z. B. von GUI- Elementen) oder die Implementierung sogenannter „ schreibgeschützter Felder“.

Unterstützung in Sprachen

Zu den Programmiersprachen, die Eigenschaften unterstützen, gehören ActionScript 3 , C# , D , Delphi / Free Pascal , eC, F# , Kotlin , JavaScript , Objective-C 2.0 , Python , Scala , Swift , Lua und Visual Basic .

Einige objektorientierte Sprachen, wie Java und C++ , unterstützen keine Eigenschaften, weshalb der Programmierer stattdessen ein Paar von Zugriffs- und Änderungsmethoden definieren muss . [ 1 ]

Oberon-2 bietet einen alternativen Mechanismus unter Verwendung von Sichtbarkeitsflags für Objektvariablen.

Andere Sprachen, die für die Java Virtual Machine entwickelt wurden , wie zum Beispiel Groovy , unterstützen Eigenschaften nativ.

Obwohl C++ keine erstklassigen Eigenschaften besitzt, können diese durch Operatorüberladung emuliert werden . [ 2 ]

Beachten Sie außerdem, dass einige C++-Compiler First-Class-Eigenschaften als Spracherweiterungen unterstützen.

In vielen objektorientierten Sprachen werden Eigenschaften als Paar von Zugriffs- und Änderungsmethoden implementiert, wobei der Zugriff dieselbe Syntax wie bei öffentlichen Feldern verwendet. Lässt man eine Methode des Paares weg, erhält man eine schreibgeschützte oder eine seltene schreibgeschützte Eigenschaft.

In einigen Sprachen ohne integrierte Unterstützung für Eigenschaften lässt sich ein ähnliches Konstrukt als einzelne Methode implementieren, die je nach Aufrufkontext entweder die zugrundeliegenden Daten zurückgibt oder verändert. Solche Techniken werden beispielsweise in Perl verwendet .

Einige Sprachen ( Ruby , Smalltalk ) erreichen eine eigenschaftsähnliche Syntax mithilfe normaler Methoden, manchmal mit einem begrenzten Maß an syntaktischem Zucker .

Syntaxvarianten

Manche Programmiersprachen folgen etablierten Syntaxkonventionen zur formalen Spezifizierung und Nutzung von Eigenschaften und Methoden.

Zu diesen Konventionen gehören:

  • Punktnotation
  • Klammernotation

Punktnotation

Das folgende Beispiel veranschaulicht die Punktnotation in JavaScript.

document.createElement ( "pre " ) ;

Klammernotation

Das folgende Beispiel veranschaulicht die Klammernotation in JavaScript.

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

Beispielsyntax

C#

class Pen { private int color ; // privates Feld // öffentliche Eigenschaft public int Color { get { return this . color ; } set { if ( value > 0 ) { this . color = value ; } } } }
// Zugriff: Pen pen = new (); int colorTmp = 0 ; // ... pen . Color = 17 ; colorTmp = pen . Color ; // ... pen . Color = ~ pen . Color ; // Bitweises Komplement ...// noch ein albernes Beispiel: pen.Color + = 1 ; // viel verständlicher als "pen.set_Color(pen.get_Color() + 1)"!

Neuere C#-Versionen erlauben auch „automatisch implementierte Eigenschaften“, bei denen das zugrundeliegende Feld für die Eigenschaft vom Compiler während der Kompilierung generiert wird. Dies bedeutet, dass die Eigenschaft eine Setter-Methode haben muss. Sie kann jedoch privat sein.

class Shape { public int Height { get ; set ; } public int Width { get ; private set ; } }

C++

C++ verfügt nicht über erstklassige Eigenschaften, aber es gibt mehrere Möglichkeiten, diese Eigenschaften in begrenztem Umfang zu emulieren. Zwei davon sind im Folgenden aufgeführt:

Verwendung von Standard-C++

import std ;using std :: same_as ;template < typename T > class Property { T value ; public : // Sicherstellen, dass T und T2 vom gleichen Typ sind template < typename U > requires same_as < T , U > T & operator = ( const U & i ) { value = i ; return * this ; }// Implizite Rückkonvertierung zu T. operator T const & () const { return value ; } };struct Foo { // Eigenschaften, die unbenannte Klassen verwenden. 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 ; };struct Bar { // Verwendung der Property<>-Vorlage. Property <bool> alpha ; Property < 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 ; // Diese Zeile führt aufgrund der Guard - Template - Memberfunktion zu einem Kompilierfehler. std :: println ( " { } , { }, {}, { } " , foo.alpha , foo.bravo , bar.alpha , bar.bravo ) ; return 0 ; }

C++, Microsoft, GCC, LLVM/clang und C++Builder-spezifisch

Ein Beispiel, adaptiert von der MSDN -Dokumentationsseite .

// 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 ; }​

D

class Pen { private int myColor ; // privates Feld // öffentliche Eigenschaft zum Abrufen der Farbe public int color () { return myColor ; } // öffentliche Eigenschaft zum Setzen der Farbe public void color ( int value ) { myColor = value ; } }
Pen pen = new Pen ; pen.color = ~ pen.color ; // Bitweises Komplement​​// Die Set-Eigenschaft kann auch in Ausdrücken verwendet werden, genau wie bei einer regulären Zuweisung. int theColor = ( pen . color = 0xFF0000 );

In D Version 2 muss jeder Property-Accessor oder -Mutator mit @property gekennzeichnet werden:

class Pen { private int myColor ; // privates Feld // öffentliche Eigenschaft abrufen @property public int color () { return myColor ; } // öffentliche Eigenschaft setzen @property public void color ( int value ) { myColor = 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 ;​Prozedur TPen . SetColor ( const AValue : TColor ) ; begin if FColor <> AValue then FColor := AValue ; Ende ;
// Zugriff auf: var Pen : TPen ; // ... Pen . Color := not Pen . Color ;(* Delphi und Free Pascal unterstützen auch eine „direkte Feld“-Syntax -Eigenschaft Farbe: TColor lesen FColor schreiben SetColor;oderEigenschaft Farbe: TColor lesen GetColor schreiben FColor;Der Compiler generiert dabei exakt denselben Code wie beim Lesen und Schreiben eines Feldes. Dies bietet die Effizienz eines Feldes mit der Sicherheit einer Eigenschaft. (Man kann keinen Zeiger auf die Eigenschaft erhalten, und der Zugriff auf das Element kann jederzeit durch einen Methodenaufruf ersetzt werden.) *)

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 = 0member 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 ; } // Fügt die Eigenschaft dem Pen-Typ selbst hinzu, kann auch // für die Instanz einzeln festgelegt werden . Object.defineProperties ( Pen.prototype , { color : { get : function ( ) { return this._color ; } , set : function ( value ) { this._color = value ; } } } ) ;
var pen = new Pen ( ); pen.color = ~ pen.color ; // Bitweises Komplement pen.color + = 1 ; // Eins addieren

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 ; // bitweises Komplement pen . color += 1 ; // eins addieren

Objective-C 2.0

@interface Pen  : NSObject @property ( copy ) NSColor * colour ; // Das Attribut "copy" bewirkt, dass die Kopie des Objekts beibehalten wird , anstatt des Originals. @end@implementation Pen @synthesize colour ; // Compiler-Direktive zur Synthese von Zugriffsmethoden. // Kann in Xcode 4.5 und höher weggelassen werden. @end

Das obige Beispiel könnte auf beliebige Weise wie folgt verwendet werden:

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 ; // Bitweises Komplement echo $p- > color ;

Python

Eigenschaften funktionieren nur für Klassen neuen Typs (Klassen mit `Type` objectals Oberklasse ) korrekt und sind erst ab Python 2.2 verfügbar (siehe den entsprechenden Abschnitt des Tutorials „ Vereinheitlichung von Typen und Klassen in Python 2.2 “). Mit Python 2.6 wurde eine neue Syntax mit Dekoratoren zur Definition von Eigenschaften eingeführt.

class Pen : _color : int # "private" Variabledef __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​​
Stift : Stift = Stift () # Zugriff: Stift . Farbe = ~ Stift . Farbe # Bitweises Komplement ...

Rubin

class Pen def initialize @color = 0 end # Definiert einen Getter für das Feld @color def color @color end# Definiert einen Setter für das Feld @color def color= ( value ) @color = value end endStift = Stift.neu Stift.Farbe = ~ Stift.Farbe # Bitweises Komplement​​​​

Ruby bietet außerdem automatische Getter/Setter-Synthesizer, die als Instanzmethoden der Klasse definiert sind.

class Pen attr_reader :brand # Generiert einen Getter für @brand (Nur Lesen) attr_writer :size # Generiert einen Setter für @size (Nur Schreiben) attr_accessor :color # Generiert sowohl einen Getter als auch einen Setter für @color (Lesen/Schreiben)def initialize @color = 0 # Innerhalb des Objekts können wir direkt auf die Instanzvariable zugreifen @brand = "Penbrand" @size = 0 . 7 # Wir könnten aber auch die Setter-Methode verwenden, die von der Instanzmethode attr_accessor definiert wird end endpen=Pen.newputspen.brand# Accesses the pen brand through the generated getterpen.size=0.5# Updates the size field of the pen through the generated setterpen.color=~pen.color

Visual Basic

Visual Basic (.NET 2003–2010)

PublicClassPenPrivate_colorAsInteger' Private fieldPublicPropertyColor()AsInteger' Public propertyGetReturn_colorEndGetSet(ByValvalueAsInteger)_color=valueEndSetEndPropertyEndClass
' Create Pen class instanceDimpenAsNewPen()' Set valuepen.Color=1' Get valueDimcolorAsInt32=pen.Color

Visual Basic (only .NET 2010)

PublicClassPenPublicPropertyColor()AsInteger' Public propertyEndClass
' Create Pen class instanceDimpenAsNewPen()' Set valuepen.Color=1' Get valueDimcolorAsInt32=pen.Color

Visual Basic 6

' in a class named clsPenPrivatem_ColorAsLongPublicPropertyGetColor()AsLongColor=m_ColorEndPropertyPublicPropertyLetColor(ByValRHSAsLong)m_Color=RHSEndProperty
' accessing:DimpenAsNewclsPen' ...pen.Color=Notpen.Color

See also

References

  1. ^"Accessors And Mutators In Java". C# Corner - Community of Software and Data Developers. Retrieved 5 January 2022.
  2. ^ „Portabilität nativer C++-Eigenschaften“ . Stack Overflow . Abgerufen am 5. Januar 2022 .
  3. ^ "Eigenschaft (C++)" . Technische Dokumentation von Microsoft . Microsoft . Abgerufen am 5. Januar 2022 .
  4. ^ „clang::MSPropertyDecl Class Reference“ . Clang: ein Frontend für die C-Sprachfamilie LLVM . Abgerufen am 5. Januar 2022 .
  5. ^ "__property Keyword Extension" . Embarcadero/IDERA Documentation Wiki . Abgerufen am 5. Januar 2022 .