Уласьцівасьць (праграмаваньне)

У пэўных аб’ектна-арыентаваных мовах праграмаваньня **уласьцівасьць** — асаблівы від члена клясы, які зьяўляецца сярэднім паміж палямі зьвестак і мэтадамі. Звычайна запіс і чытаньне ўласьцівасьці ажыцьцяўляецца як запіс і чытаньне поля, але звычайна гэта трансьлюецца ў выклікі мэтадаў для запісу і чытаньня. Сынтаксіс з выкарыстаньнем палёў дадзеных зьяўляецца прасьцейшым для ўспрыманьня і напісаньня, чым стварэньне вялікай колькасьці выклікаў мэтадаў, але выкарыстаньне мэтадаў у такіх выпадках дазваляе ажыцьцяўляць праверку зьвестак на карэктнасьць, актыўнае абнаўленьне (напрыклад, аб’ектаў інтэрфэйсу карыстальніка), і/або запіс у палі, прызначаныя толькі для чытаньня. Таму ўласьцівасьці зьяўляюцца прамежкавым этапам паміж кодам і дадзенымі экзэмпляраў клясы. Апроч гэтага ўласьцівасьці прадастаўляюць узровень інкапсуляцыі вышэйшы, чым агульныя палі зьвестак.

## Падтрымка ў мовах

**Мовы праграмаваньня, якія падтрымліваюць уласьцівасьці,** — гэта Delphi/Free Pascal, Visual Basic, C#, D, eC, і Аб’ектны C 2.0. Пэўныя аб’ектна-арыентаваныя мовы, такія як C++ і Java, не падтрымліваюць уласьцівасьці і патрабуюць ад праграмоўцы замест гэтага вызначыць пару мэтадаў — мэтада для чытаньня (аксэсар) і мэтада для запісу.

У большасьці моваў уласьцівасьці рэалізаваныя парай мэтадаў для чытаньня і для запісу, але зьвяртацца да іх можна, выкарыстоўваючы той самы сынтаксыс, як і да агульных палёў. Калі пэўны мэтад з пары адсутнічае, то гэта ўласьцівасьць робіцца даступнай *толькі для чытаньня* альбо *толькі для запісу*, але апошняе сустракаецца дастаткова рэдка.

У пэўных мовах, дзе адсутнічае ўбудаваная падтрымка ўласьцівасьцяў, падобная канструкцыя можа быць рэалізаваная як адзін мэтад, які альбо вяртае значэньне, альбо зьмяняе яго ў залежнасьці ад кантэксту ягонага выкліку. Такія тэхнікі выкарыстоўваюцца, напрыклад у мове праграмаваньня Perl.

## Прыклады выкарыстаньня

### Delphi/Free Pascal

```delphi
type TPen = class
  private
    m_Color: Integer;
    function Get_Color: Integer;
    procedure Set_Color(RHS: Integer);
  public
    property Color: Integer read Get_Color write Set_Color;
end;

function TPen.Get_Color: Integer;
begin
  Result := m_Color
end;

procedure TPen.Set_Color(RHS: Integer);
begin
  m_Color := RHS
end;
```



```delphi
// атрыманьне доступу:
var pen: TPen;
// …
pen.Color := not pen.Color;

(*
Delphi таксама падтрымлівае сынтаксіс «прамога поля»:

property Color: 'Integer read m_Color write Set_Color;

альбо

property Color: Integer read Get_Color write m_Color;

дзе кампілятар генэруе дакладна такі ж код для чытаньня і для запісу поля.
Гэта дазваляе выкарыстоўваць эфэктыўнасьць поля і бясьпеку ўласьцівасьці
(немагчыма атрымаць указальнік на уласьцівасьць, а таксама заўжды можна замяніць
прамы доступ да поля выклікам мэтаду).
*)
```


### Visual Basic

```vb
' у клясе 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
```



```vb
' атрыманьне доступу:
Dim pen As New clsPen
' …
pen.Color = Not pen.Color
```


### Visual Basic .Net

```vbnet
Public Class Pen
 
    Private m_Color as Integer ' асабістае поле

    Public Property Color as Integer ' агульнае поле
        Get
            Return m_Color
        End Get
        Set(ByVal Value as Integer)
            m_Color = Value
        End Set
    End Property

End Class
```

 

```vbnet
' атрыманьне доступу:
Dim pen As New Pen()
' …
pen.Color = Not pen.Color
```


### C#

```csharp
class Pen
{
    private int m_Color; // асабістае поле
    
    public int Color   // агульнае поле
    {
        get
        {
            return m_Color;
        }
        set 
        {
            m_Color = value;
        }
    }
}
```



```csharp
// accessing:
Pen pen = new Pen();
// …
pen.Color = ~pen.Color; // пабітавае дапаўненьне…

// яшчэ адзін дурнаваты прыклад:
pen.Color += 1; // a lot clearer than «pen.set_Color(pen.get_Color() + 1)»!
```


### D

```d
class Pen
{
    private int m_color; // асабістае поле
    
    // агульны мэтад чытаньня ўласьцівасьці
    public int color () {
        return m_color;
    }
    
    // агульны мэтад запісу ўласьцівасьці
    public int color (int value) {
        return m_color = value;
    }
}
```



```d
auto pen = new Pen;
pen.color = ~pen.color; // пабітавае дапаўненьне

// у гэтым выразе таксама можна выкарыстоўваць уласьівасьць для запісу: таксама як і звычайнае прысвойваньне
int theColor = (pen.color = 0xFF0000);
```


### Python

Уласьцівасьці карэктна працуюць толькі для клясаў, створаных у новым стылі (клясы, якія маюць `object` у якасьці продка), якія даступныя толькі ў Python 2.2 і больш новых вэрсіях (гл. адпаведную сэкцыю ў апісаньні ''Unifying types and classes in Python 2.2'').


```python
class Pen(object):
    def __init__(self):
        self.__color = 0 # "private" variable
        self.__writeonly = "You can't read this!"
    def _set_color(self, color):
        self.__color = color
    def _get_color(self):
        return self.__color
    color = property(_get_color, _set_color) # доступ на чытаньне/запіс трансьлюецца ў get/set-мэтады
    def _set_writeonly(self, new_value):
        self.__writeonly = new_value
    writeonly = property(fset = _set_writeonly) # доступ толькі на запіс (спроба чытаньня генэруе выключэньне)
```



```python
pen = Pen()
# атрыманьне доступу:
pen.color = ~pen.color # пабітавае дапаўненьне…

print pen.writeonly # узьнікае «AttributeError: unreadable attribute»
pen.writeonly = "Something Else" # <code>__writeonly</code> зараз зьяўляецца «Something Else»
print pen._Pen__writeonly
```


### PHP

```php
class Pen {
    private $_color;

    function __set($property, $value) {
        switch ($property) {
            case 'Color': $this->_color = $value; break;
        }
    }

    function __get($property) {
        switch ($property) {
            case 'Color': return $this->_color; break;
        }
    }
}
```



```php
$p = new Pen();
$p->Color = !$p->Color;
echo $p->Color;
```


### eC
 **class** Pen
 {
    Color color;
    **public** **property** Color color
    {
       **get** { **return** color; }
       **set** { color = value; }
    }
 }
 
 // Прыклад выкарыстаньня
 Pen pen { red };
 Pen pen { color = red };
 pen.color = ~pen.color; 
 pen.color += 10;
 pen.color.r = 255;
 pen.color = 0xFF0000;
 pen.color = { 255, 0, 0 };
 pen.color = ColorHSV { 0, 100, 100 };
 pen.color = ColorLab { 53, 79, 66 };
 pen.color = ColorCMYK { 0, 100, 100, 0 };

### Objective C 2.0

```objc
@interface Pen : NSObject {
   NSColor *color;
}
@property(copy) NSColor *color; // значэньні колеру заўжды капіююцца
@end

@implementation Pen
@synthesize color; // сынтэзаваньне мэтадаў доступу
@end

// Example Usage
Pen *pen = [Pen new];
pen.color = [NSColor blackColor];
float red = pen.color.redComponent;
[pen.color drawSwatchInRect:NSMakeRect(0, 0, 100, 100)];
```


## Глядзіце таксама
* Мэтад (праграмаваньне)
* Поле зьвестак (праграмаваньне)

Катэгорыя:Праграмаваньне