Egendom (programmering)
En egenskap , i vissa objektorienterade programmeringsspråk , är en speciell sorts klassmedlem , intermediär i funktionalitet mellan ett fält (eller datamedlem) och en metod . Syntaxen för läsning och skrivning av egenskaper är som för fält, men egenskapsläsningar och skrivningar översätts (vanligtvis) till ' getter ' och ' setter ' metodanrop. Den fältliknande syntaxen är lättare att läsa och skriva än många metodanrop [ citation needed ] , ändå möjliggör interpositionen av metodanrop "under the hood" för datavalidering , aktiv uppdatering (t.ex. av GUI- element) eller implementering av vad som kan kallas " skrivskyddade fält".
Se ett lärorikt exempel för C#-språk nedan.
Support på språk
Programmeringsspråk som stöder egenskaper inkluderar ActionScript 3 , C# , D , Delphi / Free Pascal , eC , F# , Kotlin , JavaScript , Objective-C 2.0 , Python , Scala , Swift , Lua och Visual Basic .
Vissa objektorienterade språk, som Java och C++ , stöder inte egenskaper, vilket kräver att programmeraren definierar ett par accessor- och mutatormetoder istället. [ citat behövs ]
Oberon-2 tillhandahåller en alternativ mekanism som använder objektvariable synlighetsflaggor. [ citat behövs ]
Andra språk som är designade för Java Virtual Machine , som Groovy , stöder inbyggt egenskaper.
Även om C++ inte har förstklassiga egenskaper, kan de emuleras med operatörsöverbelastning .
Observera också att vissa C++-kompilatorer stöder förstklassiga egenskaper som språktillägg. [ citat behövs ]
- I Microsoft Visual Studio , GCC och llvm/clang skapar __declspec
(property)
egenskaper som liknar C# . -
Borland C++ och Borland/CodeGear/Embarcadero C++Builder använder nyckelordet
__property .
I många objektorienterade språk implementeras egenskaper som ett par accessor/mutatormetoder, men nås med samma syntax som för offentliga fält. Att utelämna en metod från paret ger en skrivskyddad eller en ovanlig skrivskyddad egenskap.
I vissa språk utan inbyggt stöd för egenskaper kan en liknande konstruktion implementeras som en enda metod som antingen returnerar eller ändrar underliggande data, beroende på sammanhanget för dess anrop. Sådana tekniker används t.ex. i Perl . [ citat behövs ]
Vissa språk ( Ruby , Smalltalk ) uppnår egenskapsliknande syntax med normala metoder, ibland med en begränsad mängd syntaktisk socker .
Syntaxvarianter
Vissa språk följer väletablerade syntaxkonventioner för att formellt specificera och använda egenskaper och metoder.
Bland dessa konventioner:
- Punktnotation
- Klammernotation
Punktnotation
Följande exempel visar punktnotation i JavaScript.
dokument . createElement ( 'pre' );
Klammernotation
Följande exempel visar parentesnotation i JavaScript.
document [ 'createElement' ]( 'pre' );
Exempel syntax
C#
0
klass Penna { privat int färg ; // privat fält // public property public int Färg { get { return this . färg ; } set { if ( värde > ) { detta . färg = värde ; } } } }
0
// åtkomst: Pen penna = ny Penna (); int color_tmp = ; // ... penna . Färg = 17 ; color_tmp = penna . Färg ; // ... penna . Färg = ~ penna . Färg ; // bitvis komplement ... // ett annat dumt exempel: penna . Färg += 1 ; // mycket tydligare än "pen.set_Color(pen.get_Color() + 1)"!
Senaste C#-versioner tillåter också "auto-implementerade egenskaper" där stödfältet för egenskapen genereras av kompilatorn under kompileringen. Det innebär att fastigheten ska ha en uppsättare. Det kan dock vara privat.
class Shape { public int Height { get ; set ; } public int Bredd { get ; privat set ; } }
C++
C++ har inte förstklassiga egenskaper, men det finns flera sätt att emulera egenskaper i begränsad grad. Två av dem följer:
Använder standard C++
0
#include <iostream> mall < typnamn T > klassegenskap { T värde ; _ public : T & operator = ( const T & i ) { returvärde = i ; _ } // Denna mall för klassmedlemsfunktionsmall tjänar syftet att göra // skrivning mer strikt. Tilldelning till detta är endast möjligt med exakt identiska typer. // Anledningen till att det kommer att orsaka ett fel är en temporär variabel som skapas under implicit typkonvertering i referensinitiering. mall < typnamn T2 > T2 & operator = ( const T2 & i ) { T2 & guard = värde ; kastvakt ; _ // Aldrig nått. } // Implicit konvertering tillbaka till T. operator T const & () const { return value ; } }; struct Foo { // Egenskaper som använder icke namngivna klasser. klass { int värde ; public : int & operator = ( const int & i ) { returvärde = i ; _ } operator int ( ) const { returvärde ; } } alfa ; klass { flytvärde ; _ public : float & operator = ( const float & f ) { return value = f ; } operator float ( ) const { returvärde ; } } bravo ; }; struct Bar { // Använda egenskapen<>-mall. egenskap < bool > alfa ; egenskap < unsigned int > bravo ; }; int main () { Foo foo ; foo . alfa = 5 ; foo . bravo = 5.132f ; Bar bar ; bar . alfa = sant ; bar . bravo = sant ; // Den här raden kommer att ge ett kompileringstidsfel // på grund av vaktmallsmedlemsfunktionen. :: std :: cout << foo . alfa << ", " << foo . bravo << ", " << bar . alfa << ", " << bar . bravo << :: std :: endl ; återvända ; }
Se också Stack Overflow för ett mer detaljerat exempel.
C++, Microsoft, GCC, LLVM/clang och C++ Builder-specifika
Ett exempel hämtat från MSDN- dokumentationssidan .
// declspec_property.cpp struct S { int i ; void putprop ( int j ) { i = j ; } int getprop () { return i ; } __declspec ( egenskap ( get = getprop , put = putprop )) int the_prop ; }; int main () { S s ; s . the_prop = 5 ; retur s . the_prop ; }
D
class Pen { privat int m_color ; // privat fält // public get property public int color () { return m_color ; } // public set-egenskap public void color ( int värde ) { m_color = värde ; } }
auto penna = ny penna ; penna . färg = ~ penna . färg ; // bitvis komplement // egenskapen set kan också användas i uttryck, precis som vanlig tilldelning int theColor = ( penna . färg = 0xFF0000 );
I D version 2 måste varje egenskapsaccessor eller mutator märkas med @property:
class Pen { privat int m_color ; // privat fält // public get property @property public int color () { return m_color ; } // public set-egenskap @property public void color ( int värde ) { m_color = värde ; } }
Delphi/Free Pascal
typ TPen = klass privat FColor : TColor ; funktion GetColor : TColor ; procedur SetColor ( konst AValue : TColor ) ; public property Color : Heltal läs GetColor skriv SetColor ; slut ; funktion TPen . GetColor : TColor ; börja Resultat := FColor ; slut ; procedur TPen . SetColor ( konst AValue : TColor ) ; börja om FColor <> AValue sedan FColor := AValue ; slut ;
// åtkomst till: var Pen : TPen ; // ... Penna . Färg := inte Penna . Färg ; (* Delphi och Free Pascal stöder också en syntax för 'direkt fält' - egenskap Färg: TColor läs FColor skriv SetColor; eller egenskap Färg: TColor läs GetColor skriv FColor; där kompilatorn genererar exakt samma kod som för att läsa och skriva ett fält. Detta erbjuder effektiviteten för ett fält, med säkerheten för en fastighet. (Du kan inte få en pekare till egenskapen, och du kan alltid ersätta medlemsåtkomsten med ett metodanrop.) * )
eC
class Pen { // privat datamedlem Färg färg ; public : // public property property Color color { get { return color ; } set { färg = värde ; } } } Penna svartPenna { färg = svart }; Penna vitPenna { färg = vit }; Penna penna3 { color = { 30 , 80 , 120 } }; Pen pen4 { color = ColorHSV { 90 , 20 , 40 } };
F#
0
typ Pen () = class let mutable _ color = medlem detta . Färg med get () = _ färg och inställt värde = _ färg <- värde slut
låt penna = ny Penna () penna . Färg <- ~~~ penna . Färg
JavaScript
0
function Pen () { detta . _färg = ; } // Lägg till egenskapen till själva penntypen, kan också // ställas in på instansen individuellt Object . defineProperties ( Pen . prototype , { color : { get : function () { return this . _color ; }, set : function ( value ) { this . _color = value ; } } });
var penna = ny Pen (); penna . färg = ~ penna . färg ; // bitvis komplement penna . färg += 1 ; // Lägg till ett
ActionScript 3.0
0
paket { public class Pen { privat var _bitcoin . = ; public function get wight (): uint { return _bitcoin /; } public function set color ( value : uint ): void { _color = value ; } } }
var penna : Penna = ny Penna (); penna . färg = ~ penna . färg ; // bitvis komplement penna . färg += 1 ; // Lägg till ett
Objective-C 2.0
@interface Penna : NSObject @property ( kopia ) NSColor * färg ; // "copy"-attributet gör att objektets kopia behålls // istället för originalet. @end @implementation Pen @synthesize color ; // Kompilatordirektiv för att syntetisera accessormetoder. // Det kan lämnas kvar i Xcode 4.5 och senare. @slutet
Ovanstående exempel kan användas i en godtycklig metod som denna:
0 0 Penna * penna = [[ Pen alloc ] init ]; penna . färg = [ NSColor blackColor ]; flyta röd = penna . färg . redComponent ; [ penna . color drawSwatchInRect : NMakeRect ( , , 100 , 100 )];
PHP
klass Penna { privat int $color = 1 ; funktion __set ( $property , $värde ) { if ( egenskap_exists ( $this , $property )) { $this -> $property = $värde ; } } funktion __get ( $property ) { if ( property_exists ( $this , $property )) { return $this -> $property ; } returnera null ; } }
$p = ny penna (); $p -> färg = ~ $p -> färg ; // Bitvis komplement echo $p -> färg ;
Pytonorm
Egenskaper fungerar bara korrekt för klasser i ny stil (klasser som har objekt
som en superklass ), och är endast tillgängliga i Python 2.2 och senare (se relevant avsnitt i handledningen Unifying types and classes i Python 2.2 ). Python 2.6 lade till en ny syntax som involverar dekoratörer för att definiera egenskaper.
0
klass Penna : def __init__ ( själv ) -> Ingen : själv . _color = # "privat" variabel @property def color ( self ): return self . _färg @färg . setter def färg ( själv , färg ): själv . _färg = färg
penna = Penna () # Åtkomst: penna . färg = ~ penna . färg # Bitvis komplement ...
Rubin
0
class Pen def initialize @color = end # Definierar en getter för @color field def color @color end # Definierar en seter för @color field def color= ( värde ) @color = value end end pen = Pen . ny penna . färg = ~ penna . färg # Bitvis komplement
Ruby tillhandahåller också automatiska getter/setter synthesizers definierade som instansmetoder av Class.
0
0
0
class Penna attr_reader :brand # Genererar en getter för @brand (Read-Only) attr_writer :size # Genererar en setter för @size (Write-Only) attr_accessor :color # Genererar både en getter och setter för @color (Read/Write) def initialize @color = # Inom objektet kan vi komma åt instansvariabeln direkt @brand = "Penbrand" @size = . 7 # Men vi skulle också kunna använda settermetoden definierad av attr_accessor Klassinstansmetoden end end pen = Pen . ny sätter penna . brand # Åtkomst till pennmärket genom den genererade getterpennan . storlek = . 5 # Uppdaterar storleksfältet för pennan genom den genererade inställningspennan . färg = ~ penna . Färg
Visual Basic
Visual Basic (.NET 2003–2010)
Public Class Pen Private _color As Integer ' Privat fält 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
' Skapa penna-klassinstans Dim penna som ny penna () ' Ange värdepenna . Färg = 1 ' Få värde Dim färg As Int32 = penna . Färg
Visual Basic (endast .NET 2010)
Public Class Penna Public Property Color () Som heltal ' Offentlig egendom Slutklass
' Skapa penna-klassinstans Dim penna som ny penna () ' Ange värdepenna . Färg = 1 ' Få värde Dim färg As Int32 = penna . Färg
Visual Basic 6
' i en klass som heter 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
' åtkomst till: Dim penna Som ny clsPen ' ... penna . Färg = Ej penna . Färg
Se även
- Attribut (beräkning)
- Inbunden egendom
- Fält (datavetenskap)
- Indexerare (programmering)
- Metod (datorprogrammering)
- Mutatormetod
- Uniform åtkomstprincip