stringtranslate.com

Собственность (программирование)

Свойство в некоторых объектно-ориентированных языках программирования это особый вид члена класса , промежуточный по функциональности между полем (или членом данных) и методом . Синтаксис для чтения и записи свойств такой же, как для полей, но чтение и запись свойств (обычно) транслируются в вызовы методов « getter » и « setter ». Синтаксис, подобный синтаксису поля, легче читать и писать, чем многие вызовы методов, [ требуется ссылка ], однако размещение вызовов методов «под капотом» позволяет выполнять проверку данных , активное обновление (например, элементов GUI ) или реализацию того, что можно назвать «полями только для чтения».

Поддержка на языках

Языки программирования, поддерживающие свойства, включают ActionScript 3 , C# , D , Delphi / Free Pascal , eC, F# , Kotlin , JavaScript , Objective-C 2.0 , Python , Scala , Swift , Lua и Visual Basic .

Некоторые объектно-ориентированные языки, такие как Java и C++ , не поддерживают свойства, требуя от программиста вместо этого определения пары методов доступа и мутатора . [1] [ необходима цитата ]

Oberon-2 предоставляет альтернативный механизм, использующий флаги видимости переменных объекта. [ необходима ссылка ]

Другие языки, разработанные для виртуальной машины Java , такие как Groovy , изначально поддерживают свойства.

Хотя в C++ нет первоклассных свойств, их можно эмулировать с помощью перегрузки операторов . [2]

Также обратите внимание, что некоторые компиляторы C++ поддерживают свойства первого класса как расширения языка. [ необходима ссылка ]

Во многих объектно-ориентированных языках свойства реализованы как пара методов доступа/мутатора, но доступ к ним осуществляется с использованием того же синтаксиса, что и для публичных полей. Исключение метода из пары приводит к свойству только для чтения или необычному свойству только для записи .

В некоторых языках без встроенной поддержки свойств подобная конструкция может быть реализована как один метод, который либо возвращает, либо изменяет базовые данные в зависимости от контекста его вызова. Такие методы используются, например, в Perl . [ необходима цитата ]

В некоторых языках ( Ruby , Smalltalk ) синтаксис, подобный свойствам, достигается с помощью обычных методов, иногда с ограниченным количеством синтаксического сахара .

Варианты синтаксиса

Некоторые языки следуют устоявшимся синтаксическим соглашениям для формального указания и использования свойств и методов.

Среди этих конвенций:

Точечная нотация

Следующий пример демонстрирует точечную нотацию в JavaScript.

document.createElement ( 'pre ' ) ;

Обозначение скобок

Следующий пример демонстрирует использование скобок в JavaScript.

документ [ '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 ; } } } }                                 
// доступ: Pen pen = new Pen (); int color_tmp = 0 ; // ... pen . Color = 17 ; color_tmp = pen . Color ; // ... pen . Color = ~ pen . Color ; // побитовое дополнение ...              // еще один глупый пример: pen . Color += 1 ; // гораздо понятнее, чем "pen.set_Color(pen.get_Color() + 1)"!   

Последние версии C# также допускают "автоматически реализуемые свойства", где резервное поле для свойства генерируется компилятором во время компиляции. Это означает, что свойство должно иметь сеттер. Однако оно может быть закрытым.

класс Форма { public int Высота { получить ; установить ; } public int Ширина { получить ; частный набор ; } }                 

С++

C++ не имеет первоклассных свойств, но существует несколько способов эмулировать свойства в ограниченной степени. Два из них следующие:

Использование стандартного C++

#include <iostream> template < typename T > class property { T value ; public : T & Operator = ( const T & i ) { return value = i ; } // Этот шаблон функции-члена класса служит для того, чтобы сделать типизацию более строгой. Присвоение ему возможно только для точно идентичных типов. // Причина, по которой это вызовет ошибку, — временная переменная, созданная при неявном преобразовании типа при инициализации ссылки. template < typename T2 > T2 & Operator = ( const T2 & i ) { T2 & Guard = value ; throw Guard ; // Никогда не достигается. }                                            // Неявное преобразование обратно в T. оператор T const & () const { return value ; } };          struct Foo { // Свойства, использующие неименованные классы. class { int value ; public : int & Operator = ( const int & i ) { return value = i ; } Operator int () const { return value ; } } alpha ;                                класс { значение float ; public : float & оператор = ( const float & f ) { возвращаемое значение = f ; } оператор float () const { возвращаемое значение ; } } браво ; };                           struct Bar { // Использование шаблона свойства<>. свойство < bool > alpha ; свойство < unsigned int > bravo ; };          int main () { Foo foo ; foo . alpha = 5 ; foo . bravo = 5.132f ;            Bar bar ; bar . alpha = true ; bar . bravo = true ; // Эта строка выдаст ошибку времени компиляции // из-за функции-члена шаблона guard. :: std :: cout << foo . alpha << ", " << foo . bravo << ", " << bar . alpha << ", " << bar . bravo << :: std :: endl ; return 0 ; }                            

Более подробный пример можно найти на сайте Stack Overflow.

C++, Microsoft, GCC, LLVM/clang и C++Builder-специфичные

Пример взят со страницы документации MSDN.

// declspec_property.cpp struct S { int i ; void putprop ( int j ) { i = j ; }             int getprop () { return i ; }      __declspec ( свойство ( получить = getprop , положить = putprop )) int the_prop ; };       int main () { S s ; s . the_prop = 5 ; return s . the_prop ; }        

Д

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 ; // побитовое дополнение       // свойство set также можно использовать в выражениях, как и обычное присваивание int theColor = ( pen . color = 0xFF0000 );     

В версии D 2 каждый аксессор или мутатор свойства должен быть отмечен @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

тип TPen = класс private FColor : TColor ; функция GetColor : TColor ; процедура SetColor ( const AValue : TColor ) ; публичное свойство Color : Integer чтение GetColor запись SetColor ; конец ;                     function TPen.GetColor : TColor ; begin Result : = FColor ; end ;     процедура TPen . SetColor ( const AValue : TColor ) ; начать, если FColor <> AValue , то FColor := AValue ; конец ;           
// доступ : var Pen : TPen ; // ... Pen.Color : = not Pen.Color ;     (* Delphi и Free Pascal также поддерживают синтаксис «прямого поля» -свойство Цвет: TColor чтение FColor запись SetColor;илисвойство Цвет: TColor чтение GetColor запись FColor;где компилятор генерирует точно такой же код, как для чтения и записи поля. Это обеспечивает эффективность поля с безопасностью свойства. (Вы не можете получить указатель на свойство, и вы всегда можете заменить доступ к члену вызовом метода.) *)

ес

класс Pen { // закрытый член данных Color color ; public : // открытое свойство 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 } };                                                         

Фа#

тип Pen () = класс пусть изменяемый _ цвет = 0         элемент this . Цвет с get () = _ color и set value = _ color <- value end            
пусть ручка = новая ручка () ручка . Цвет <- ~~~ ручка . Цвет      

JavaScript

function Pen () { this._color = 0 ; } // Добавляем свойство к самому типу Pen, также может быть // установлено для экземпляра индивидуально Object.defineProperties ( Pen.prototype , { color : { get : function ( ) { return this._color ; } , set : function ( value ) { this._color = value ; } } } ) ;                        
var pen = new Pen (); pen . color = ~ pen . color ; // побитовое дополнение pen . color += 1 ; // Добавить один          

ActionScript 3.0

package { public class Pen { private var _bitcoin . = 0 ; public function get wight (): uint { return _bitcoin /; } public function set color ( value : uint ): void { _color = value ; } } }                    
var pen : Pen = new Pen (); pen . color = ~ pen . color ; // побитовое дополнение pen . color += 1 ; // добавить единицу          

Objective-C 2.0

@interface  Pen  : NSObject @property ( copy ) NSColor * colour ; // Атрибут "copy" приводит к сохранению копии объекта // вместо оригинала. @end   @implementation  Pen @synthesize colour ; // Директива компилятора для синтеза методов доступа. // Ее можно оставить в Xcode 4.5 и более поздних версиях. @end 

Приведенный выше пример можно использовать в произвольном методе, например:

Pen * pen = [[ Pen alloc ] init ]; pen . colour = [ NSColor blackColor ]; float red = pen . colour . redComponent ; [ pen . colour drawSwatchInRect : NSMakeRect ( 0 , 0 , 100 , 100 )];                

PHP

класс  Pen {  private  int  $color  =  1 ; функция  __set ( $property ,  $value )  {  если  ( property_exists ( $this ,  $property ))  {  $this -> $property  =  $value ;  }  } функция  __get ( $property )  {  если  ( property_exists ( $this ,  $property ))  {  вернуть  $this -> $property ;  }  вернуть  null ;  } }
$p  =  new  Pen (); $p -> color  =  ~ $p -> color ;  // Побитовое дополнение echo  $p -> color ;

Питон

Свойства работают правильно только для классов нового стиля (классов, которые имеют objectв качестве суперкласса ) и доступны только в Python 2.2 и более поздних версиях (см. соответствующий раздел учебника Унификация типов и классов в Python 2.2). В Python 2.6 добавлен новый синтаксис, включающий декораторы для определения свойств.

класс  Pen :  def  __init__ ( self )  ->  None :  self._color = 0  # "частная "  переменная  @property  def  color ( self ):  вернуть  self . _color @ color.setter def color ( self , color ) : self._color = color      
pen  =  Pen () # Доступ: pen . color  =  ~ pen . color  # Побитовое дополнение ...

Рубин

class Pen def initialize @color = 0 end # Определяет геттер для поля @color def color @color end              # Определяет сеттер для поля @color def color= ( value ) @color = value end end      ручка = ручка . новая ручка . цвет = ~ ручка . цвет # Побитовое дополнение     

Ruby также предоставляет автоматические синтезаторы геттеров/сеттеров, определенные как методы экземпляра класса.

class Pen attr_reader :brand # Генерирует геттер для @brand (только чтение) attr_writer :size # Генерирует сеттер для @size (только запись) attr_accessor :color # Генерирует как геттер, так и сеттер для @color (чтение/запись)           def initialize @color = 0 # Внутри объекта мы можем получить доступ к переменной экземпляра напрямую @brand = "Penbrand" @size = 0 . 7 # Но мы также могли бы использовать метод setter, определенный методом экземпляра класса attr_accessor end end             pen = Pen.new puts pen.brand # Получает доступ к бренду пера через сгенерированный геттер pen.size = 0.5 # Обновляет поле размера пера через сгенерированный сеттер pen.color = ~ pen.color         

Визуальный базовый

Visual Basic (.NET 2003–2010)

Public Class Pen Private _color As Integer ' Частное поле         Public Property Color () As Integer ' Public property Get Return _color End Get Set ( ByVal value As Integer ) _color = value End Set End Property                     Конец класса 
' Создать экземпляр класса Pen Dim pen As New Pen ()    ' Установить значение пера . Цвет = 1  ' Получить значение Dim color As Int32 = pen . Color     

Visual Basic (только .NET 2010)

Загон для общественного класса   Публичное свойство Color () As Integer ' Публичное свойство     Конец класса 
' Создать экземпляр класса Pen Dim pen As New Pen ()    ' Установить значение пера . Цвет = 1  ' Получить значение Dim color As Int32 = pen . Color     

Visual Basic 6

' в классе с именем clsPen Private m_Color As Long   Открытое свойство Get Color () As Long Color = m_Color Конечное свойство         Открытое свойство Пусть цвет ( ByVal RHS As Long ) m_Color = RHS Конечное свойство          
' доступ : Dim pen As New clsPen ' ... pen.Color = Not pen.Color       

Смотрите также

Ссылки

  1. ^ "Accessors And Mutators In Java". Уголок C# - Сообщество разработчиков программного обеспечения и данных . Получено 5 января 2022 г.
  2. ^ "Переносимость собственных свойств C++". Stack Overflow . Stack Overflow . Получено 5 января 2022 г. .
  3. ^ "property (C++)". Техническая документация Microsoft . Microsoft . Получено 5 января 2022 г. .
  4. ^ "clang::MSPropertyDecl Class Reference". Clang: интерфейс семейства языков C для LLVM . Получено 5 января 2022 г.
  5. ^ "__property Keyword Extension". Embarcadero/IDERA Documentation Wiki . Получено 5 января 2022 г.