Свойство (программирование)
Эта статья нуждается в дополнительных цитатах для проверки . ( январь 2022 г. ) |
Свойство — в некоторых объектно-ориентированных языках программирования это особый вид члена класса , промежуточный по функциональности между полем (или членом данных) и методом . Синтаксис чтения и записи свойств аналогичен полям, но чтение и запись свойств (обычно) преобразуются в ' getter ' и ' setter вызовы методов '. Полевой синтаксис легче читать и писать, чем многие вызовы методов. [ нужна ссылка ] тем не менее, вставка вызовов методов «под капотом» позволяет осуществлять проверку данных , активное обновление (например, элементов графического интерфейса ) или реализацию того, что можно назвать « только для чтения полями ».
Поддержка на языках [ править ]
Языки программирования, поддерживающие свойства, включают ActionScript 3 , C# , D , Delphi / Free Pascal , eC , F# , Kotlin , JavaScript , Objective-C 2.0 , Python , Scala , Swift , Lua и Visual Basic .
Некоторые объектно-ориентированные языки, такие как Java и C++ , не поддерживают свойства, требуя от программиста вместо этого определить пару методов доступа и мутатора . [1] [ нужна ссылка ]
Оберон-2 предоставляет альтернативный механизм, использующий флаги видимости переменных объекта. [ нужна ссылка ]
Другие языки, разработанные для виртуальной машины Java , такие как Groovy , изначально поддерживают свойства.
Хотя в C++ нет свойств первого класса, их можно эмулировать с помощью перегрузки операторов . [2]
Также обратите внимание, что некоторые компиляторы C++ поддерживают свойства первого класса как расширения языка. [ нужна ссылка ]
- В Microsoft Visual Studio [3] GCC и llvm/clang , [4] тот
__declspec(property)
создает свойства, аналогичные C# . - Borland C++ и Borland/CodeGear/Embarcadero C++Builder используют
__property
ключевое слово. [5]
Во многих объектно-ориентированных языках свойства реализованы как пара методов доступа/мутатора, но доступ к ним осуществляется с использованием того же синтаксиса, что и для открытых полей. Исключение метода из пары приводит к свойству , доступному только для чтения или необычному свойству , доступному только для записи .
В некоторых языках, где нет встроенной поддержки свойств, подобная конструкция может быть реализована как один метод, который либо возвращает, либо изменяет базовые данные в зависимости от контекста ее вызова. Такие методы используются, например, в Perl . [ нужна ссылка ]
Некоторые языки ( Ruby , Smalltalk ) реализуют синтаксис, подобный свойствам, используя обычные методы, иногда с ограниченным количеством синтаксического сахара .
Варианты синтаксиса [ править ]
Некоторые языки следуют устоявшимся синтаксическим соглашениям для формального определения и использования свойств и методов.
Среди этих конвенций:
- Точечное обозначение
- Обозначение в скобках
Точечная запись [ править ]
В следующем примере демонстрируется запись через точку в JavaScript.
document.createElement('pre');
Обозначение в скобках [ править ]
В следующем примере демонстрируется обозначение скобок в JavaScript.
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 Pen();
int color_tmp = 0;
// ...
pen.Color = 17;
color_tmp = 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)"!
Последние версии C# также допускают «автоматически реализуемые свойства», когда резервное поле для свойства создается компилятором во время компиляции. Это означает, что свойство должно иметь установщик. Однако оно может быть частным.
class Shape
{
public int Height { get; set; }
public int Width { get; private set; }
}
С++ [ править ]
![]() | Эта статья может сбивать с толку или быть непонятной читателям . ( Октябрь 2016 г. ) |
В C++ нет свойств первого класса, но существует несколько способов эмулировать свойства в ограниченной степени. Два из них следуют ниже:
Использование стандартного C++ [ править ]
#include <iostream>
template <typename T> class property {
T value;
public:
T & operator = (const T &i) {
return value = i;
}
// This template class member function template serves the purpose to make
// typing more strict. Assignment to this is only possible with exact identical types.
// The reason why it will cause an error is temporary variable created while implicit type conversion in reference initialization.
template <typename T2> T2 & operator = (const T2 &i) {
T2 &guard = value;
throw guard; // Never reached.
}
// Implicit conversion back to T.
operator T const & () const {
return value;
}
};
struct Foo {
// Properties using unnamed classes.
class {
int value;
public:
int & operator = (const int &i) { return value = i; }
operator int () const { return value; }
} alpha;
class {
float value;
public:
float & operator = (const float &f) { return value = f; }
operator float () const { return value; }
} bravo;
};
struct Bar {
// Using the property<>-template.
property <bool> alpha;
property <unsigned int> bravo;
};
int main () {
Foo foo;
foo.alpha = 5;
foo.bravo = 5.132f;
Bar bar;
bar.alpha = true;
bar.bravo = true; // This line will yield a compile time error
// due to the guard template member function.
::std::cout << foo.alpha << ", "
<< foo.bravo << ", "
<< bar.alpha << ", "
<< bar.bravo
<< ::std::endl;
return 0;
}
См. также «Переполнение стека» более подробный пример в разделе .
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(property(get = getprop, put = 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; // bitwise complement
// the set property can also be used in expressions, just like regular assignment
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 [ править ]
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.
(You can't get a pointer to the property, and you can always replace the member
access with a method call.)
*)
ЕС [ править ]
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 <- value
end
let pen = new Pen()
pen.Color <- ~~~pen.Color
JavaScript [ править ]
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;
}
}
});
var pen = new Pen();
pen.color = ~pen.color; // bitwise complement
pen.color += 1; // Add one
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; // bitwise complement
pen.color += 1; // add one
Objective-C 2.0 [ править ]
@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
Приведенный выше пример можно использовать в произвольном методе, например:
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; // Bitwise complement
echo $p->color;
Питон [ править ]
Свойства работают корректно только для классов нового стиля (классов, у которых есть object
как суперкласс ) и доступны только в Python 2.2 и новее (см. соответствующий раздел руководства «Объединение типов и классов в Python 2.2» ). В Python 2.6 добавлен новый синтаксис, включающий декораторы для определения свойств.
class Pen:
def __init__(self) -> None:
self._color = 0 # "private" variable
@property
def color(self):
return self._color
@color.setter
def color(self, color):
self._color = color
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 также предоставляет автоматические синтезаторы получения/установки, определенные как методы экземпляра класса.
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
Visual Basic [ править ]
Visual Basic (.NET 2003–2010) [ править ]
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
Visual Basic (только .NET 2010) [ править ]
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
Visual Basic 6 [ править ]
' 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
См. также [ править ]
- Атрибут (вычисление)
- Связанное свойство
- Область (информатика)
- Индексатор (программирование)
- Метод (компьютерное программирование)
- Метод мутатора
- Единый принцип доступа
Ссылки [ править ]
- ^ «Акцессоры и мутаторы в Java» . C# Corner — Сообщество разработчиков программного обеспечения и данных . Проверено 5 января 2022 г.
- ^ «Переносимость свойств Native C++» . Переполнение стека . Переполнение стека . Проверено 5 января 2022 г.
- ^ «свойство (C++)» . Техническая документация Майкрософт . Майкрософт . Проверено 5 января 2022 г.
- ^ "clang::MSPropertyDecl Справочник класса" . Clang: интерфейс семейства языков C для LLVM . Проверено 5 января 2022 г.
- ^ «Расширение ключевого слова __property» . Wiki-документация Embarcadero/IDERA . Проверено 5 января 2022 г.