Определения в программе Fore.NET представляют собой составляющие части программы. Программы Fore.NET упорядочиваются посредством пространств имен, которые могут содержать определения типов и вложенных пространств имен. Определения типов используются для описания классов, структур, интерфейсов, перечислений и делегатов. Виды членов, которые допустимы внутри определения типа, зависят от определяемого типа. Например, определение класса может содержать определения констант, полей, методов, свойств, событий и конструкторов.
Определение описывает имя в пространстве определений, к которому относится определение. Является ошибкой компиляции иметь два или более определения членов с одинаковым именем в одном пространстве определений. Также не допускается иметь в пространстве определений определения различных видов членов с одним именем.
Имеется несколько различных видов пространств определений как описано ниже:
Глобальное пространство определений содержит определения, которые не являются членами какого-либо пространства имен.
Каждое пространство имен образует собственное пространство определений.
Каждое определение класса, структуры или интерфейса создает новое пространство определений.
Каждое перечисление создает новое пространство определений, членами которого являются именованные константы перечисления.
Каждый функциональный член создает новое пространство определений, называемое локальным пространством определений, членами которого являются параметры и локальные переменные.
Порядок, в котором производится определение имен, не имеет значения в общем случае. Порядок определений имеет значение только в следующих случаях:
Порядок определений полей и локальных переменных определяет порядок, в котором выполняется их инициализация.
Порядок определения именованных констант в перечислении важен в том случае, когда опускаются определения их числовых значений.
//Пространство имён A определено в глобальном пространстве имён и создает собственное пространство определений
Namespace A
//Определение интерфейса в пространстве имён
Interface ITest
End Interface;
//Определение класса в пространстве имён
Class Test: ITest
End Class;
//Определение перечисления в пространстве имён
Enum Mode
//Определение элементов перечисления
Low, Middle, High
End Enum;
End Namespace;
Пространства имен и типы состоят из членов. Обращение к членам сущности обычно производится посредством использования квалифицированного имени, которое состоит из ссылки на сущность, символа точки и имени члена.
Члены типа либо описываются в самом типе, либо наследуются от его базового класса. Когда тип является производным от базового все члены базового класса кроме конструкторов становятся членами производного класса. Уровень доступа членов базового класса не влияет на их наследование. Однако член может быть не доступен в производном классе по причине определенного для него уровня доступа или в случае его скрытия.
Пространства имен, типы и методы, определенные вне какого-либо другого пространства имен, являются членами глобального пространства имен.
//Интерфейс - член пространства имён
Interface ITest
//Определение членов интерфейса, которые в дальнейшем будут реализованы в классе
Function Run(ExecuteParams: Mode): Integer;
Property Status: Integer
Get;
End Property Status;
End Interface;
//Класс - член пространства имён
Class Test1: ITest
//Определение членов класса
iResult: Integer;
iStatus: Integer;
Public Function Run(ExecuteParams: Mode): Integer;
Begin
iStatus := 0;
//...
Select Case ExecuteParams
//...
//Различные варианты выполнения в соответствии со значением входного параметра
//...
Case Mode.Low: iResult := 1;
Case Mode.Middle: iResult := 2;
Case Mode.High: iResult := 3;
End Select;
//...
iStatus := 100;
Return iResult;
End Function;
Public Property Status: Integer
Get
Begin
Return iStatus
End Get
End Property;
End Class;
//Перечисление - член пространства имён
Enum Mode
//Определение элементов перечисления
Low, Middle, High
End Enum;
В определениях членов позволяется управлять уровнем доступа к ним. Видимость члена определяется уровнем доступа, указанным в его определении, а также уровнем доступа содержащего его типа, если таковой имеется.
Имеются следующие уровни доступа:
Открытый, в случае указания модификатора Public в определении члена. В этом случае доступ к члену не ограничен.
Родовой, в случае указания модификатора Protected в определении члена. В этом случае доступ к члену ограничен классом, в котором он определен, а также классами, производными от него.
Сборочный, в случае указания модификатора Friend в определении члена. В этом случае доступ к члену ограничен сборкой (программой), в которой он определен.
Сборочный родовой, в случае указания модификатора Protected Friend в определении члена. В этом случае доступ к члену ограничен либо текущей сборкой, либо классами, производными от класса, содержащего данный член или при соблюдении обоих условий.
Закрытый, в случае указания модификатора Private в определении члена. В этом случае доступ к члену ограничен только классом, содержащим данный член.
В зависимости от контекста, в котором производится определение члена, возможно использование только некоторых модификаторов доступа. В случае, если определение члена не содержит модификатора доступа, его видимость определяется уровнем доступа по умолчанию.
Пространства имен неявно имеют открытый доступ. Использование модификаторов доступа в определениях пространств имен недопустимо.
Типы, определенные внутри единиц компиляции или пространств имен, могут иметь открытый или сборочный уровень доступа. По умолчанию они имеют сборочный уровень доступа.
Члены классов могут иметь любой из пяти определенных уровней доступа и по умолчанию имеют закрытый уровень доступа.
Члены структур могут иметь открытый, сборочный или закрытый уровень доступа, т.к. структуры неявно являются завершенными типами. По умолчанию они имеют закрытый уровень доступа.
Члены интерфейсов неявно имеют открытый уровень доступа. Использование модификаторов доступа в определениях членов интерфейсов не допускается.
Члены перечислений неявно имеют открытый уровень доступа. Использование модификаторов доступа в определениях членов перечислений не допускается.
Областью видимости члена называется объединение частей программы, в которых допустимо обращение к данному члену. Для целей определения областей видимости различных членов программы будем называть вложенными членами те из них, которые определены внутри некоторого другого типа. Остальные члены (не определенные внутри какого-либо типа) будем называть внешними. Текстом программы будем считать весь текст программы во всех файлах исходных текстов (единиц компиляции). Текстом типа будем считать весь текст, заключенный между заголовком и закрывающей конструкцией End в определениях классов, структур, интерфейсов или перечислений.
Область видимости стандартных типов (таких как Object, Integer или Double) не ограничена.
Область видимости внешнего типа T в программе P определяется следующим образом:
Если тип T имеет открытый уровень доступа, то областью видимости типа Т является программа P и все другие программы, которые на нее ссылаются.
Если тип T имеет сборочный уровень доступа, то областью видимости типа Т является программа P.
Из этих определений следует, что область видимости любого внешнего типа включает как минимум программу, в которой он определяется.
Область видимости вложенного члена М, определенного в типе T в программе P определяется следующим образом:
Если член М имеет открытый уровень доступа, то его область видимости совпадает с областью видимости типа T.
Если член М имеет родовой сборочный уровень доступа, то определим D как объединение текста программы P и текстов всех типов, производных от Т и определенных вне P. Областью видимости М будет пересечение области видимости Т с D.
Если член М имеет родовой уровень доступа, то определим D как объединение текста типа T и текстов всех типов, производных от Т. Областью видимости М будет пересечение области видимости Т с D.
Если член М имеет сборочный уровень доступа, то его областью видимости является пересечение области видимости типа Т и программы P.
Если член М имеет закрытый уровень доступа, то его областью видимости является текст типа Т.
Из этих определений следует, что область видимости любого вложенного члена как минимум включает текст типа, в котором он определен. Также область видимости вложенного члена никогда не превосходит область видимости типа, в котором он определен.
При обращении к типу или члену М наличие доступа определяется следующим образом:
Если М определен внутри типа и этот тип недоступен, то возникнет ошибка компиляции.
Если М имеет открытый уровень доступа, то доступ разрешается, иначе:
Если М имеет родовой сборочный уровень доступа, то доступ разрешается, если он производится внутри программы, в которой определен М или внутри типа, являющегося производным от типа содержащего определение М.
Если М имеет родовой уровень доступа, то доступ разрешается если производится внутри типа, являющегося производным от типа содержащего определение М.
Если М имеет сборочный уровень доступа, то доступ разрешается если он производится внутри программы, в которой определен М.
Если М имеет закрытый уровень доступа, то доступ разрешается если он производится внутри типа, в котором определен М.
В противном случае тип или член являются недоступными и возникает ошибка компиляции.
Определенные конструкции в языке требуют, чтобы тип имел уровень доступа не ниже чем член или другой тип. Уровень доступа типа Т не ниже чем уровень доступа типа или члена M если область видимости Т целиком включает в себя область видимости M. Другими словами тип Т всегда должен быть доступен там, где является доступным M.
Определены следующие ограничения:
Уровень доступа родительского класса не должен быть ниже уровня доступа класса, для которого он является родительским.
Уровень доступа для интерфейсов, являющихся базовыми для другого интерфейса, должен быть не ниже уровня доступа этого интерфейса.
Типы параметров и возвращаемого значения делегата должны иметь уровень доступа не ниже чем уровень доступа самого делегата.
Тип константы должен иметь уровень доступа не ниже чем уровень доступа самой константы.
Тип поля и типы его параметров должны иметь уровень доступа не ниже чем уровень доступа самого поля.
Типы параметров и возвращаемого значения метода должны иметь уровень доступа не ниже чем уровень доступа самого метода.
Тип свойства должен иметь уровень доступа не ниже чем уровень доступа самого свойства.
Тип события должен иметь уровень доступа не ниже чем уровень доступа самого события.
Типы параметров экземплярного конструктора должны иметь уровень доступа не ниже чем уровень доступа самого.
Методы, экземплярные конструкторы и свойства характеризуются своими сигнатурами:
Сигнатура метода состоит из имени метода, типов и видов (по значению, по ссылке, выходной) его формальных параметров в порядке их объявления слева направо. Сигнатура метода специально не включает тип возвращаемого значения, а также модификатор ParamArray, который может быть указан у последнего параметра.
Сигнатура экземплярного конструктора состоит из типов и видов (по значению, по ссылке, выходной) его формальных параметров в порядке их объявления слева направо. Сигнатура экземплярного конструктора специально не включает модификатор ParamArray, который может быть указан у последнего параметра.
Сигнатура свойства состоит из его имени, типов и видов (по значению, по ссылке, выходной) его формальных параметров в порядке их объявления слева направо. Сигнатура свойства специально не включает его тип, а также модификатор ParamArray, который может быть указан у последнего параметра свойства.
Сигнатуры позволяют использовать механизм перегрузки членов в классах, структурах и интерфейсах. Перегрузка позволяет определить внутри класса, структуры или интерфейса несколько членов одного вида (метод, событие или конструктор) с одинаковым именем при условии что их сигнатуры различны.
Важно отметить, что члены определенные в одном типе не могут иметь сигнатуры, которые отличаются только наличием модификаторов Var и Out. Для успешной компиляции необходимо чтобы имелись какие-либо другие различия.
Областью действия (scope) имени называется часть программы, в которой это имя может быть использовано без его квалификации. Области действия могут быть вложенными и внутренняя область действия может переопределять значение имени из внешней области действия. Имя из внешней области действия в этом случае называется скрытым и доступ к нему может осуществляться только посредством квалифицированного имени.
Скрытие имен возникает в случае когда области действия имен разных сущностей программы пересекаются через вложение или наследование.
Скрытие через вложение. Скрытие имен через вложение может возникать в результате вложенности пространств имен или типов в них определенных, а также в результате определения параметров методов и локальных переменных в них.
Скрытие через наследование. Скрытие через наследование возникает, когда классы или структуры переопределяют имена, которые были унаследованы от базовых классов.
В определённых контекстах программы требуется указание имени пространства имён, либо имени типа. Обе формы имён записываются как один или более идентификаторов, разделенных точками.
namespace-name:
namespace-or-type-name
type-name:
namespace-or-type-name
namespace-or-type-name:
identifier type-argument-listopt
namespace-or-type-name . identifier type-argument-listopt
Каждое пространство имен или тип имеет полностью квалифицированное имя (полное имя), которое уникальным образом идентифицирует это пространство имен или тип среди остальных. Полностью квалифицированное имя пространства имен или типа N определяется следующим образом:
Если N является членом глобального пространства имен, то его полностью квалифицированное имя - это N.
В противном случае его полностью квалифицированным именем является S.N, где S - это полностью квалифицированное имя пространства имен или типа, в котором определено N.
В языке Fore.NET реализовано автоматическое управление памятью. Разработчику нет необходимости вручную выделять память для объектов и освобождать её, когда объекты больше не используются. Автоматическое управление памятью осуществляется сборщиком мусора. Жизненный цикл объекта выглядит следующим образом:
При создании объекта выполняется конструктор, выделяется память и предоставляется доступ к полученному экземпляру объекта.
Компилятор и сборщик мусора отслеживает ссылки на объект.
Если объект более не используется или недоступен, то для него автоматически вызывается деструктор.
После отработки деструктора объект считается уничтоженным и более недоступным.
Со временем сборщик мусора освободит память, связанную с этим объектом.
Сборщик мусора сохраняет информацию об объектах и использует её для принятия решения по управлению памятью. Автоматическое управление осуществляется при работе с объектами, разработанными в прикладном коде на Fore.NET. В некоторых случаях может потребоваться принудительное управление сборщиком мусора, для этого используются методы класса System.GC (mscorlib.dll). Например, при работе с системными объектами репозитория, ядро которых разработано с использованием COM-технологии.
Public Shared Sub Main(Params: StartParams);
Var
//...
MB: IMetabase;
Report: IPrxReport;
//...
Begin
//...
MB := Params.Metabase;
Report := MB.ItemById["Report"].Bind() As IPrxReport;
//...
//Работа с отчётом и данными, содержащимися в нём
//...
//Освобождение объекта
Report := Null;
//Сборка мусора, освобождение памяти, которая была выделена под отчёт и данные
System.GC.Collect();
//...
//Дальнейшая работа с репозиторием и другими объектами
//...
End Sub;
При работе с COM-объектами для их своевременного освобождения используйте метод System.Runtime.InteropServices.Marshal.ReleaseComObject. При работе с ресурсами языка Fore из Fore.NET также может потребоваться принудительная сборка мусора. Для этого используются методы CollectFullGarbage и CollectGarbage. Более подробно о них читайте в статье базы знаний «Использование ресурсов «Форсайт. Аналитическая платформа» в сторонних приложениях > Сборка мусора».
См. также: