Перайсьці да зьместу

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

Зьвесткі зь Вікіпэдыі — вольнай энцыкляпэдыі

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

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

[рэдагаваць | рэдагаваць крыніцу]

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

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

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

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

[рэдагаваць | рэдагаваць крыніцу]
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;
// атрыманьне доступу:
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;

дзе кампілятар генэруе дакладна такі ж код для чытаньня і для запісу поля.
Гэта дазваляе выкарыстоўваць эфэктыўнасьць поля і бясьпеку ўласьцівасьці
(немагчыма атрымаць указальнік на уласьцівасьць, а таксама заўжды можна замяніць
прамы доступ да поля выклікам мэтаду).
*)
' у клясе 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
' атрыманьне доступу:
Dim pen As New clsPen
' ...
pen.Color = Not pen.Color
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
' атрыманьне доступу:
Dim pen As New Pen()
' ...
pen.Color = Not pen.Color
class Pen
{
    private int m_Color; // асабістае поле
    
    public int Color   // агульнае поле
    {
        get
        {
            return m_Color;
        }
        set 
        {
            m_Color = value;
        }
    }
}
// accessing:
Pen pen = new Pen();
// ...
pen.Color = ~pen.Color; // пабітавае дапаўненьне...

// яшчэ адзін дурнаваты прыклад:
pen.Color += 1; // a lot clearer than "pen.set_Color(pen.get_Color() + 1)"!
class Pen
{
    private int m_color; // асабістае поле
    
    // агульны мэтад чытаньня ўласьцівасьці
    public int color () {
        return m_color;
    }
    
    // агульны мэтад запісу ўласьцівасьці
    public int color (int value) {
        return m_color = value;
    }
}
auto pen = new Pen;
pen.color = ~pen.color; // пабітавае дапаўненьне

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

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

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) # доступ толькі на запіс (спроба чытаньня генэруе выключэньне)
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
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;
        }
    }
}
$p = new Pen();
$p->Color = !$p->Color;
echo $p->Color;
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 };
 
 @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)];