Для того чтобы узнать какие поля свойства и методы есть у класса можно
Поля класса являются переменными, объявленными внутри класса. Они предназначены для хранения данных во время работы экземпляра класса (объекта). Ограничений на тип полей в классе не предусмотрено. В описании класса поля должны предшествовать методам и свойствам. Обычно по-
ля используются для обеспечения выполнения операций внутри класса.
При объявлении имен полей принято к названию добавлять заглавную букву F.Например FSomeField.
Итак, поля предназначены для использования внутри класса. Однако класс должен каким-либо образом взаимодействовать с другими классами или программными элементами приложения. В подавляющем большинстве случаев класс должен выполнить с некоторыми данными определенные действия и представить результат.
Для полученияи передачи данных в классе применяются свойства. Для объявления свойств в классе используется зарезервированное слово property.
Свойства представляют собой атрибуты, которые составляют индивидуальность объекта и помогают описать его. Например, обычная кнопка в окне приложения обладает такими свойствами, как цвет, размеры, положение. Для экземпляра класса “кнопка” значения этих атрибутов задаются при по-
мощи свойств — специальных переменных, определяемых ключевым словом property. Цвет может задаваться свойством color, размеры — свойствами Width И Height и т.д.
Так как свойство обеспечивает обмен данными с внешней средой, то для доступа к его значению используются специальные методы класса. Поэтому обычно свойство определяется тремя элементами: полем и двумя методами,которые осуществляют его чтение/запись:
type
TAnObject = class(TObject)
function GetColor: TSomeType;
procedure SetColor(ANewValue: TSomeType);
property AColor: TSomeType read GetColor write SetColor;
end;
В данном примере доступ к значению свойства AColor осуществляется через вызовы методов GetColor и SetColor. Однако в обращении к этим методам в явном виде нет необходимости: достаточно написать:
AnObject.AColor := AValue;
AVariable := AnObject.AColor;
и компилятор самостоятельно оттранслирует обращение к свойству AColor в вызовы методов Getcoior или Setcoior. To есть внешне свойство выглядит в точности как обычное поле, но за всяким обращением к нему могут стоять нужные вам действия. Например, если у вас есть объект, представляющий собой квадрат на экране, и его свойству “цвет” вы присваиваете значение “белый”, то произойдет немедленная перерисовка, приводящая реальный цвет на экране в соответствие со значением свойства. Выполнение этой операции осуществляется методом, который связан с установкой значения свойства “цвет”.В методах, входящих в состав свойств, может осуществляться проверка устанавливаемой величины на попадание в допустимый диапазон значений и вызов других процедур, зависящих от вносимых изменений. Если же потребности в специальных процедурах чтения и/или записи нет, можно вместо имен методов применять имена полей. Рассмотрим следующую конст-
рукцию:
TPropObject = class(TObject)
FValue: TSomeType;
procedure DoSomething;
function Correct(AValue: Integer):boolean;
procedure SetValue(NewValue: Integer);
property AValue: Integer read FValue write SetValue;
end;
procedure TPropObject.SetValue(NewValue: Integer);
begin
if (NewValueOFValue) and Correct (NewValue) then FValue := NewValue;
DoSomething;
end;
В этом примере чтение значения свойства AValue означает просто чтение поля F/aiue. Зато при присвоении значения внутри SetValue вызывается сразу два метода.Если свойство должно только читаться или записываться, в его описании может присутствовать соответствующий метод:
type
TAnObject = class(TObject)
property AProperty: TSomeType read GetValue;
end;
В этом примере вне объекта значение свойства можно лишь прочитать; попытка присвоить свойству AProperty значение вызовет ошибку компиляции.
Для присвоения свойству значения по умолчанию используется ключевое СЛОВО default:
property Visible: boolean read FVisible write SetVisible default True;
Это означает, что при запуске программы свойство будет установлено компилятором В True.
Свойство может быть и векторным; в этом случае оно внешне выглядит как массив:
property APoints[Index : Integer]:TPoint read GetPoint write SetPoint;
На самом деле в классе может и не быть соответствующего поля — массива. Напомним, что вся обработка обращений к внутренним структурам класса может быть замаскирована.Для векторного свойства необходимо описать не только тип элементов массива, но также имя и тип индекса. После ключевых слов read и write в этом случае должны стоять имена методов — использование здесь полей массивов недопустимо. Метод, читающий значение векторного свойства, должен быть описан как функция, возвращающая значение того же типа, что и элементы свойства, и имеющая единственный параметр того же типа и с тем же именем, что и индекс свойства:
function GetPoint(Index:Integer):TPoint;
Аналогично, метод, помещающий значения в такое свойство, должен первым параметром иметь индекс, а вторым — переменную нужного типа (которая может быть передана как по ссылке, так и по значению):
procedure SetPoint(Index:Integer; NewPoint:TPoint);
У векторных свойств есть еще одна важная особенность. Некоторые классы в Delphi (списки TList, наборы строк TStrings) “построены” вокруг основного векторного свойства (см. гл. 7). Основной метод такого класса дает доступ к некоторому массиву, а все остальные методы являются как бы вспомогательными. Специально для облегчения работы в этом случае векторное свойство может быть описано с ключевым словом default:
type
TMyObject = class;
property Strings[Index: Integer]: string read Get write Put; default;
end;
Если у объекта есть такое свойство, то можно его не упоминать, а ставить индекс в квадратных скобках сразу после имени объекта:
var AMyObject: TMyObject;
begin
AMyObject.Strings[1] := ‘ F i r s t 1 ; {первый способ}
AMyObj ect[2] := ‘Second’; {второй способ}
end.
Будьте внимательны, применяя зарезервированное слово default, — как мы увидели, для обычных и векторных свойств оноупотребляется в разных случаях и с различным синтаксисом.О роли свойств в Delphi красноречиво говорит следующий факт: у всех имеющихся в распоряжении программиста стандартных классов 100% полей недоступны и заменены базирующимися на них свойствами. Рекомендуем при разработке собственных классов придерживаться этого же правила. Внимательный читатель обратил внимание, что при объяснении терминов “поле” и “свойство” мы использовали понятие метода, и наверняка понял его общий смысл. Итак, методом называется объявленная в классе функция или процедура, которая используется для работы с полями и свойствами класса. Согласно принципам ООП (см. разд. “Инкапсуляция” далее в этой главе), обращаться к свойствам класса можно только через его методы. От обычных процедур и функций методы отличаются тем, что им при вызове
передается указатель на тот объект, который их вызвал. Поэтому обрабатываться будут данные именно того объекта, который вызвал метод. На некоторых особенностях использования методов мы остановимся ниже.
Источник
Общая структура типа C# представляет собой описание типа и определение полей и методов. Поля – хранят данные, методы ими манипулируют (изменяют значения).
Свойства созданы как комбинация метода и поля в одном члене типа для лаконичности и безопасности кода.
Лаконичность достигается тем, что для считывания или изменения значения поля в свойствах используются два метода. Безопасность – ограничением доступа к полям типа только свойствами. Для программиста типа, свойство выглядит методом, поскольку его нужно определять и реализовывать. Для программиста использующего объект типа – полем, поскольку обращение к полю и свойству идентичны. Инкапсуляция.
Для доступа к значению поля в свойстве используются методы, которые создаются средой выполнения, но реализуются программистом. Их два – get и set. Get используется в случае чтения значения поля и называется акссесором, set – при изменении значения, называется мутатором. Общее название для мутатора и аксессора – методы доступа.
Объявление свойства
Методы определяются внутри блока типа. Сигнатура в последовательности при объявлении:
уровень доступа;
тип свойства;
имя свойства.
После сигнатуры определения следует два блока кода с реализацией аксессора и/или мутатора:
public class GrandMa
{
private int fullAge = 69; / закрытое поле для хранения возраста. Доступ к полю возможен только из свойства и методов класса.
public int FullAge
{
get
{
return fullAge;
}
set
{
if (value > 0)
{
fullAge = value;
}
}
}
}
Допустимо реализовывать свойство только с одним из методов. Свойство, содержащее только аксессор называется полем только для чтения, свойство с одним мутатором – свойством только для записи.
Аксессор get
Если в свойстве использован акссессор, то подобно методу, свойство должно возвращать значение поля, которое акссессор считывает. Тип поля должен соответствовать типу возвращаемого значения свойства.
Блок кода аксессора похож на реализацию метода и выполняется по всем правилам синтаксиса С#. Пример объявления свойства только с аксессором:
class Elephant
{
private string elName; // Закрытое поле. Считывание значения возможно только методами и свойствами класса.
public string ElName // открытое свойство для считывания значения поля elName. Возвращает значение типа string.
{
// реализация аксессора
get
{
return elName; // возврат значения поля elName
}
}
}
Использование аксессора в пользовательском в коде эквивалентно считыванию на прямую из поля:
Elephant el1 = new Elephant();// создание объекта типа Elephant
System.Console.WriteLine(el1.ElName); // вывод значения поля elName на системную консоль
В блоке реализации аксессора можно менять значение считываемого поля, но крайне не рекомендуется, поскольку это может иметь массу побочных эффектов, которые при увеличении объёма кода трудно отследить:
class Elephant
{
private string elName; // Закрытое поле. Считывание значения возможно только методами и свойствами класса.
public string ElName // открытое свойство для считывания значения поля elName. Возвращает значение типа string.
{
// реализация аксессора
get
{
return elName + “ Сидорович”; // возврат значения поля elName с изменением. Изменения будут происходить при каждом использовании свойства внутри объекта. Плохой стиль, для изменения значения лучше использовать мутатор.
}
}
}
Мутатор set
Мутатор, или метод set по спецификации вызова поход на метод с возвращаемым значение типа void и одним параметром. public void SetValue (object value). Среда выполнения сама его вызывает в точке указанной программистом с прописанной им реализацией.
При реализации мутатора в блоке кода свойства нужно помнить о неявном участии параметра value, который выполняет функцию буфера, промежуточной переменной, значение которой нужно предать полю типа.
Пример реализации:
class Elephant
{
private string elName; // Закрытое поле. Считывание значения возможно только методами и свойствами класса.
public string ElName // открытое свойство для считывания значения поля elName. Возвращает значение типа string.
{
get
{
return elName;
}
// Реализация мутатора
set
{
elName = value; // полю elName присваивается значение неявного параметра value.
}
}
}
В блоке кода мутатора нельзя вводить локальную переменную value, поскольку уже есть такая переменная, неявно переданная в виде параметра. Такой код компилятор не пропустит и выдаст ошибку:
class Elephant
{
private string elName; // Закрытое поле. Считывание значения возможно только методами и свойствами класса.
public string ElName // открытое свойство для считывания значения поля elName. Возвращает значение типа string.
{
// Реализация мутатора
set
{
String value = “Фыва”; // нельзя, параметр value уже определен.
elName = value; // полю elName присваивается значение неявного параметра value.
}
}
}
Метод доступа set используется неявно при присвоении значения свойству, как в следующем примере:
Elephant el1 = new Elephant();// создание объекта типа Elephant
El1.ElName = “Никки”; // присваиваем значение полю elName через свойство ElName неявно вызывается мутатор.
System.Console.WriteLine(el1.ElName); // вывод значения поля elName на системную консоль
Модификаторы свойств и уровни доступа
Свойства, подобно типам в которых определяются по уровню доступа могут быть: открытыми (public), частными (private), защищенными (protected). Доступ к методам свойства осуществляется в соответствии с модификатором.
Свойство может быть статичным (static), и будет доступным без необходимости создавать экземпляр типа, в котором оно определено.
Допустимо объявлять свойства виртуальными, для возможности их переопределения в производных классах с помощью ключевого слова override или переопределения и запечатывания при помощи ключевого слова sealed.
Свойство можно сделать абстрактным при помощи ключевого слова abstract, оставив блок реализации пустым, в дальнейшем реализовав свойство в дочерних (производных) классах.
Применительно к определению свойств запрещено одновременное употребление следующих пар модификаторов:
static – virtual;
static – abstract;
static – override.
Допустимо использовать разные уровни доступа для аксессора и мутатора, что бывает удобно, если нужно обеспечить доступность чтения поля, но при этом защитить его от записи методами производных классов.
Пример:
private string description = “Какое-то описание”;
// создаем свойство для чтения/записи значения в поле description с разными модификаторами доступа для аксессора и мутатора
public string Description
{
// открытый аксессор
get
{
return description;
}
// защищенный мутатор
protected set
{
description = value;
}
}
Если для одного из методов доступа не указан модификатор доступа, то компилятор вставит его неявно руководствуясь модификатором доступа свойства.
Автоматически реализуемые свойства
Программист при реализации свойства связывает его с полем. Часто поля и свойства имеют одинаковые имена, чтобы программист, взглянув, мог сразу догадаться, для работы с каким полем создано свойство.
При работе с типами, в которых реализованы свойства, поля вовсе не вызываются, поскольку любой доступ к ним организован через свойства. Зачем в таком случае создавать поля вручную? И если код свойств не требует изысков программирования, то не проще ли доверить их создание компилятору.
Автоматически реализуемые свойства – это свойства, которые автоматически реализует компилятор, он же создает и поле, для доступа к которому создается свойство.
Сигнатура определения автоматически реализуемого свойства:
тип имя { get; set; }
Сам блок инструкций в таком свойстве отсутствует и для мутатора и для аксессора. После ключевых слов get и set ставится символ завершения инструкции «;».
Автоматически реализуемые свойства доступны в версии C# 3.0 и новее. С 6 версии спецификации языка доступна возможность объявить и инициализировать скрытое поле через упрощенный синтаксис свойства, вот так:
public string Nickname { get; set; } = “Забияка”;
Источник
Классы и объекты
В языке Object Pascal классы — это специальные типы данных, используемые для описания объектов. Соответственно объект, имеющий тип какого-либо класса, является экземпляром (instance) этого класса или переменной этого типа. Класс представляет собой особый тип записи, имеющий в своем составе такие элементы (члены, member), как поля, свойства и методы. Лом класса аналогичны полям записи и служат для хранения информации об объекте. Методами называются процедуры и функции, предназначенные для обработки полей. Свойства занимают промежуточное положение между полями и методами. С одной стороны, свойства можно использовать как поля, например, присваивая им значения с помощью инструкции присваивания; с другой стороны, внутри класса доступ к значениям свойств выполняют методы класса. Описание класса имеет следующую структуру:
Туре <Имя класса> = class (<Имя класса-родителя>)
private
<Частные описания>;
protected
<Защищенные описания>;
public
<Общедоступные описания>;
published
<Опубликованные описания>;
end;
В приведенной структуре описаниями являются объявления свойств, методов и событий.
Пример описания класса:
type
TColorCircle = class(TCircle);
FLeft,
FTop,
FRight,
FBottom: Integer;
Color: TColor;
end;
Здесь класс TColorCircle создается на основе родительского класса TCircle. По сравнению с родительским, новый класс дополнительно содержит четыре поля типа Integer и одно поле типа TColor.
Если в качестве родительского используется класс TObject, который является базовым классом для всех классов, то его имя после слова Class можно не указывать. Тогда первая строка описания будет выглядеть так: type TNewClass = class
Для различных элементов класса можно устанавливать разные права доступа (видимости), для чего в описании класса используются отдельные разделы, обозначенные специальными спецификаторами видимости.
Разделы private и protected содержат защищенные описания, которые доступны внутри модуля, в котором они находятся. Описания из раздела protected, кроме того, доступны для порожденных классов за пределами названного модуля.
Раздел public содержит общедоступные описания, которые видимы в любом месте программы, где доступен сам класс.
Раздел published содержит опубликованные описания, которые в дополнение к общедоступным описаниям порождают динамическую (т.е. во время выполнения программы) информацию о типе (Run-Time Type Information, RTTI). По этой информации при выполнении приложения производится проверка на принадлежность элементов объекта тому или иному классу. Одним из назначений раздела published является обеспечение доступа к свойствам объектов при конструировании приложений. В Инспекторе объектов видны те свойства, которые являются опубликованными. Если спецификатор published не указан, то он подразумевается по умолчанию, поэтому любые описания, расположенные за строкой с указанием имени класса, считаются опубликованными. Объекты как экземпляры класса объявляются в программе в разделе var как обычные переменные. Например:
var
CCircle1: TColorCircle;
CircleA: TCircle;
Как и в случае записей, для обращения к конкретному элементу объекта (полю, свойству или методу) указывается имя объекта и имя элемента, разделенные точкой, т.е. имя элемента является составным.
Пример обращения к полям объекта:
var
CCircle1: TColorCircle;
begin
CCircle1.FLeft:=5; CCircle1.FTop:=1;
end;
Здесь приведено непосредственное обращение к полям объекта, обычно это делается с помощью методов и свойств класса.
Поля
Поле класса представляет собой данные, содержащиеся в классе. Поле описывается как обычная переменная и может принадлежать к любому типу.
Пример описания полей:
type TNewClass = class(TObject)
private
FCode: integer;
FSign: char:
FNote: string;
end;
Здесь новый класс TNewClass создается на основе базового класса TObject и получает в дополнение три новых поля FCode, FSign и FNote, имеющих, соответственно, целочисленный, символьный и строковый типы. Согласно принятому соглашению имена полей должны начинаться с префикса F (от англ. Field — поле).
При создании новых классов класс-потомок наследует все поля родителя, при этом удалить или переопределить эти поля нельзя, но можно добавить новые. Таким образом, чем дальше по иерархии какой-либо класс находится от родительского класса, тем больше полей он имеет.
Напомним, что изменение значений полей обычно выполняется с помощью методов и свойств объекта.
Свойства
Свойства (property) реализуют механизм доступа к полям. Каждому свойству соответствуют поле, содержащее значение свойства, и два метода, обеспечивающих доступ к этому полю. Описание свойства начинается со слова property, при этом типы свойства и соответствующего поля должны совпадать. Ключевые слова read и write являются зарезервированными внутри объявления свойства и служат для указания методов класса, с помощью которых выполняется чтение значения поля, связанного со свойством, или запись нового значения в это поле.
Пример описания свойств:
type TNewClass = class(TObject)
private
FCode: integer;
FSign: char:
FNote: string;
published
property Code: integer read FCode write FCode;
property Sign: char read FSign write FSign;
property Note: string read FNote write FNote;
Для доступа к полям FCode, FSign и FNote, которые описаны в защищенном разделе и недоступны для других классов, используются свойства Code, Sign и Note соответственно.
Методы
Метод представляет собой подпрограмму (процедуру или функцию), являющуюся элементом класса. Описание метода похоже на описание обычной подпрограммы модуля. Заголовок метода располагается в описании класса, а сам код метода находится в разделе реализации. Имя метода в разделе реализации является составным и включает в себя тип класса.
Например, описание метода Button1Click будет выглядеть так:
interface
type
TForm1 = class (TForm)
Button1: TButton;
procedure Button1Click (Sender: TObject);
end;
implementation
procedure TForm1. Button1Click (Sender: TObject);
begin
Close;
end;
Метод, объявленный в классе, может вызываться различными способами, что зависит от вида этого метода. Вид метода определяется модификатором, который указывается в описании класса после заголовка метода и отделяется, от заголовка точкой с запятой. Приведем некоторые модификаторы:
J Virtual — виртуальный метод;
J Dynamic — динамический метод;
J Override – переопределяемый метод;
J Message — обработка сообщения;
J Abstract — абстрактный метод.
По умолчанию все методы, объявленные в классе, являются статическими и вызываются как обычные подпрограммы.
Методы, которые предназначены для создания или удаления объектов, называются конструкторами и деструкторами соответственно. Описания данных методов отличаются от описания обычных процедур только тем, что в их заголовках стоят ключевые слова constructor и destructor. В качестве имен конструкторов и деструкторов в базовом классе TObject и многих других классах используются имена Create и Destroy.
Прежде чем обращаться к элементам объекта, его нужно создать с помощью конструктора. Например: ObjectA := TOwnClass.Create;
Конструктор выделяет память для нового объекта в “куче” (heap), задает нулевые значения для порядковых полей, значение nil — для указателей и полей-классов, строковые поля устанавливает пустыми, а также возвращает указатель на созданный объект.
При выполнении конструктора часто также осуществляется инициализация элементов объекта с помощью значений, передаваемых в качестве параметров конструктора. Приведем примеры использования конструктора и деструктора:
type
TShape = class(TGraphicControl)
private
FPen: TPen;
procedure PenChanged(Sender: TObject);
public
constructor Create(Owner: TComponent); override;
destructor Destroy; override;
…
end;
// Описание конструктора Create класса TShape
constructor TShape.Create(Owner: TComponent);
begin
inherited Create(Owner); // Инициализация унаследованных частей
Width := 65; // Изменение унаследованных свойств
Height := 65;
FPen := TPen.Create; // Инициализация новых полей
FPen.OnChange := PenChanged;
end;
В конструкторе класса-потомка сначала вызывается конструктор родителя, а затем выполняются остальные действия. В классе-потомке директива override (переопределить) обеспечивает возможность родительскому классу использовать новый метод. Ключевое слово inherited служит для вызова методов родительского класса.
Источник