Процедуры-элементы
 
Процедуры с полным доступом к элементам Type or Class.

Декларация и объявление
Объявление и определение процедур-элементов.
Использование
Вызов процедур-элементов.
Скрытый параметр This
Неявный доступ к экземпляру, с которым нестатические процедуры-элементы вызываются.
Права доступа
Ссылки на другие элементы в процедурах-элементах.
Перегрузка
Объявление двух или более процедур-элементов с этим именем.
Статические процедуры-элементы
Отличия от нестатических процедур-элементов.

Термин «процедура-элемент» относится к статическим и нестатическим процедурам-элементам, если не указано иное.

Декларация и объявление

Процедуры-элементы объявляются так же, как обычные процедуры уровня модуля , за исключением исключением того, что они были декларируются в Type или Class, а определяются вне его [1].

При определении процедуры-элемента, имя процедуры должно быть с префиксом имени Type или Class и оператором доступа (Оператор . (доступ к элементу)). Будет ошибкой определение процедуры-элемента без соответствующей декларации в Type или Class.

В следующем примере декларируются и определяются процедуры-элементы Sub и Function:

'' foo1.bi

Type foo
    Declare Sub f (As Integer)
    Declare Function g As Integer

    i As Integer
End Type

Sub foo.f (n As Integer)
    Print n
End Sub

Function foo.g As Integer
    Return 420
End Function


Использование

Процедуры-элементы вызываются так же, как элементы данных, то есть, их имя начинается с названия экземпляра объекта и оператора доступа(Оператор . (доступ к элементу)) [2].

В следующем примере, используя код из прошлого примера, вызываются процедуры-элементы Sub и Function:

'' ... Foo с не-статическими элементами ...
#include once "foo1.bi"

Dim bar As foo
bar.f(bar.g())



Скрытый параметр This

Процедуры-элементы на самом деле имеют дополнительный параметр, в отличии от объявленного с [3]. Когда они вызываются, используя имя экземпляра и оператора . (доступ к элементу), ссылка на этот экземпляр передается вместе с другими аргументами при вызове, позволяя процедуре-элементу иметь прямой доступ к экземпляру.

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

В большинстве случаев нет необходимости использовать This , потому что процедуры-элементы и так имеют прямой доступ к элементам данных своего объекта с помощью оператора . (доступ к элементу). Единственно необходимый случай использования This , это когда доступ к данным объекта скрыт локальной переменной или параметром процедуры-элемента (то есть имя локальной переменной или параметра имеет такое же имя , как и у элемента данных объекта)

Примечание:
Чтобы получить доступ к дублированным символам, определенным вне TYPE используйте: .SomeSymbol (или ..SomeSymbol если внутри блока With..End With).


В следующем примере используется ключевое слово This для обращения к данным элемента, имя которого скрыто параметром и локальной переменной:

Type foo
    Declare Sub f (i As Integer)
    Declare Sub g ()

    i As Integer = 420
End Type

Sub foo.f (i As Integer)
    '' элемент T.i скрыт параметром, поэтому для доступа к элементу нужно использовать THIS:
    Print this.i
End Sub

Sub foo.g ()
    '' элемент T.i скрыт локальной переменной, поэтому для доступа к элементу нужно использовать THIS:
    Dim i As Integer
    Print this.i
End Sub


Права доступа

В отличие от обычных процедур уровня модуля процедуры-элементы имеют права полного доступа к элементам Type или Class, в котором продекларированы; это относиться к public, protected и private элементам Type или Class.

Перегрузка

Процедуры-элементы могут быть объявлены с тем же именем, как другая процедура-элемент, если параметры отличаются количеством или типом. Это называется перегрузкой.

Только параметры используются для определения, является ли данная процедура допустимой для перегрузки. Например, Type или Class может иметь статические и не статические процедуры-элементы с одним именем, или процедуры-элементы Sub и Function с таким же именем, но в примере ниже вы увидите, что только различие параметров в действительности разрешают перегрузку.

В отличие от процедур уровня модуля, которые должны определять перегрузку с помощью ключевого слова Overload , процедуры-элементы перегружены по умолчанию и не нуждаются в указании с помощью Overload.

Type T
    Declare Sub f
    
    '' Другое кол-во параметров:
    Declare Sub f (As Integer)
    
    '' Другой тип параметров:
    Declare Sub f (ByRef As String)
    
    '' Снова тип параметра отличается:
    Declare Function f (As UByte) As Integer
    
    '' следующие три элемента вызовут ошибку,
    '' потому что кол-во и тип параметров не отличается:

    '' Declare Function f As Integer
    '' Declare Function f (As UByte) As String
    '' Declare Static Function f (As UByte) As Integer

    '' ...
    somedata As Any Ptr
End Type


Статические процедуры-элементы

Статические процедуры-элементы декларируются и объявляются так же, как нестатические процедуры-элементы, но с ключевым словом Static перед декларацией и объявлением.

Процедуры-элементы, объявленные с помощью ключевого слова Static , должны быть продекларированы тоже с ключевым словом Static в определении Type или Class, или возникнет ошибка компилятора.

Не путайте это с определениями процедур, которые определяют статическую память для своих переменных и объектов путем добавления ключевого слова Static в заголовке процедуры. Ключевое слово Static можно использовать в обоих контекстах, однако; статические процедуры-элементы могут быть определены со статической памятью для переменной и объекта.

В следующем примере объявляется две статических процедуры-элементы, первая из которых имеет статическое хранилище для переменной и объекта. Обратите внимание, что ключевое слово Static является необязательным в определении процедуры-элемента:

'' foo2.bi

Type foo
    Declare Static Sub f (As Integer)
    Declare Static Function g As Integer

    i As Integer
End Type

Static Sub foo.f (n As Integer) Static
    Print n
End Sub
    
Function foo.g As Integer
    Return 420
End Function


Статические процедуры-элементы могут быть вызваны так же, как нестатические процедуры-элементы, используя имя экземпляра объекта и через оператор . (доступ к элементу) имя процедуры-элемента.

Они также могут вызываться , путем указания имени процедуры с именем Type или Class, в котором они были продекларированы и конечно для доступа все так же используется (Operator . (Member Access)). Другими словами экземпляр не является обязательным для вызова статической процедуры-элемента.

В следующем примере, с помощью прошлого кода, используется оба способа вызова статической процедуры-элемента:

'' ... foo со статическими процедурами-элементами  ...
#include once "foo2.bi"

Dim bar As foo
bar.f(foo.g())


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

В следующем примере показано как ссылаться к нестатическому элементу из статического процедуры-элемента:

Type foo
    Declare Static Sub f (ByRef As foo)

    i As Integer
End Type

Sub foo.f (ByRef self As foo)
    '' ОК, сам является экземпляром класса foo:
    Print self.i

    '' приведет к ошибке ниже запись: Print i
    '' не удается получить доступ к нестатическим элементам, нет экземпляра foo:
    '' Print i
End Sub


[1] В будущем процедуры-элементы могут быть определены в пределах определения Type или Class.
[2] Статические процедуры-элементы не требуют экземпляр объекта для того, чтобы вызываться.
[3] Статические процедуры-элементы не имеют дополнительный параметр THIS, добавляемый компилятором и поэтому не могут получить доступ на экземпляр объекта, из которого они были вызваны.