Jump to content

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

Свойство в некоторых объектно-ориентированных языках программирования это особый вид члена класса , промежуточный по функциональности между полем (или членом данных) и методом . Синтаксис чтения и записи свойств аналогичен полям, но чтение и запись свойств (обычно) преобразуются в ' 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++ поддерживают свойства первого класса как расширения языка. [ нужна ссылка ]

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

В некоторых языках, где нет встроенной поддержки свойств, подобная конструкция может быть реализована как один метод, который либо возвращает, либо изменяет базовые данные в зависимости от контекста ее вызова. Такие методы используются, например, в 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; }
}

С++ [ править ]

В 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

См. также [ править ]

Ссылки [ править ]

  1. ^ «Акцессоры и мутаторы в Java» . C# Corner — Сообщество разработчиков программного обеспечения и данных . Проверено 5 января 2022 г.
  2. ^ «Переносимость свойств Native C++» . Переполнение стека . Переполнение стека . Проверено 5 января 2022 г.
  3. ^ «свойство (C++)» . Техническая документация Майкрософт . Майкрософт . Проверено 5 января 2022 г.
  4. ^ "clang::MSPropertyDecl Справочник класса" . Clang: интерфейс семейства языков C для LLVM . Проверено 5 января 2022 г.
  5. ^ «Расширение ключевого слова __property» . Wiki-документация Embarcadero/IDERA . Проверено 5 января 2022 г.
Arc.Ask3.Ru: конец переведенного документа.
Arc.Ask3.Ru
Номер скриншота №: 7086d880409748b032a8674fd3532e32__1687605840
URL1:https://arc.ask3.ru/arc/aa/70/32/7086d880409748b032a8674fd3532e32.html
Заголовок, (Title) документа по адресу, URL1:
Property (programming) - Wikipedia
Данный printscreen веб страницы (снимок веб страницы, скриншот веб страницы), визуально-программная копия документа расположенного по адресу URL1 и сохраненная в файл, имеет: квалифицированную, усовершенствованную (подтверждены: метки времени, валидность сертификата), открепленную ЭЦП (приложена к данному файлу), что может быть использовано для подтверждения содержания и факта существования документа в этот момент времени. Права на данный скриншот принадлежат администрации Ask3.ru, использование в качестве доказательства только с письменного разрешения правообладателя скриншота. Администрация Ask3.ru не несет ответственности за информацию размещенную на данном скриншоте. Права на прочие зарегистрированные элементы любого права, изображенные на снимках принадлежат их владельцам. Качество перевода предоставляется как есть. Любые претензии, иски не могут быть предъявлены. Если вы не согласны с любым пунктом перечисленным выше, вы не можете использовать данный сайт и информация размещенную на нем (сайте/странице), немедленно покиньте данный сайт. В случае нарушения любого пункта перечисленного выше, штраф 55! (Пятьдесят пять факториал, Денежную единицу (имеющую самостоятельную стоимость) можете выбрать самостоятельно, выплаичвается товарами в течение 7 дней с момента нарушения.)