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 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