Активные свойства
 

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

Простые свойства
Объявление и использование свойств для получения и установки.
Индексируемые свойства
Свойства с дополнительным параметром.

Простые свойства


Свойства объявляются подобно процедуре-элементу, за исключением того, что используется ключевое слово Property вместо Sub или Function. Например, давайте рассматривать класс окна для системы Windows или библиотеки GUI.

Type Window
Private:
    As String title_
End Type

Dim As Window w


Чтобы установить название окна, свойство для установки может быть добавлено:

Type Window
    Declare Property title(ByRef s As String)
Private:
    As String title_
End Type

Property Window.title(ByRef s As String)
    this.title_ = s
End Property

Dim As Window w
w.title = "My Window"


Это очень похоже на элемент Sub, как он принимает параметр и обновляет объект в новое состояние на основе параметра. Однако синтаксис для отправки этого параметра является Basic подобным назначением, но не вызовом функции. Назначая новое значение для свойства title, процедура свойства будет вызвана автоматически с заданным новым значением и потом можно обновить окно, чтобы отразить изменения. Все зависит от объекта , как внутри представляется свойство.

Если придерживаться данного дизайна свойства, то ему можно назначить только одно значение, и в результате у свойства не может быть больше чем одного параметра. (Но это не значит что в свойства нельзя устанавливать больше параметров. Просто при другом дизайне вызова, свойства выглядят как-то "сумбурно")

После установки текста окна, можно также извлечь его значение. Вот как можно добавить свойство для получения:

Type Window
    '' установка
    Declare Property title(ByRef s As String)
    '' получение
    Declare Property title() As String
Private:
    As String title_
End Type

'' установка
Property Window.title(ByRef s As String)
    this.title_ = s
End Property

'' получение
Property Window.title() As String
    Return this.title_
End Property

Dim As Window w
w.title = "My Window"
Print w.title


Метод получения очень похож на Function. Он должен возвращать текущее значение свойства, и это позволяет текущему значению вычисляться из других внутренних значений, при необходимости. Обратите внимание, что оба метода используют один и тот же идентификатор, говорящий о том , что эти два метода принадлежат к одному свойству.

Так же, как с перегрузкой метода, можно указать несколько свойств для установки, если они имеют различные типы параметров:

Type Window
    Declare Property title(ByRef s As String)
    Declare Property title(ByVal i As Integer)
    Declare Property title() As String
Private:
    As String title_
End Type

Property Window.title(ByRef s As String)
    this.title_ = s
End Property

Property Window.title(ByVal i As Integer)
    this.title_ = "Number: " & i
End Property

Property Window.title() As String
    Return this.title_
End Property

Dim As Window w
w.title = "My Window"
Print w.title
w.title = 5
Print w.title


Вот пример, который делает тоже самое, что и прошлый, но без активных свойств:

Type Window
    Declare Sub set_title(ByRef s As String)
    Declare Sub set_title(ByVal i As Integer)
    Declare Function get_title() As String
Private:
    As String title
End Type

Sub Window.set_title(ByRef s As String)
    this.title = s
End Sub

Sub Window.set_title(ByVal i As Integer)
    this.title = "Number: " & i
End Sub

Function Window.get_title() As String
    Return this.title
End Function

Dim As Window w
w.set_title("My Window")
Print w.get_title()
w.set_title(5)
Print w.get_title()


Код работает практически так же, только синтаксис отличается. Свойства специально разработаны, чтобы  объединить концепции получения\установки более понятным Basic синтаксисом для присваивания и доступа к элементам. Все зависит от программистов, какой способ они предпочитают.

Вот пример демонстрирующий текстовый пользовательский интерфейс класса окна, позволяющий задать положение и название с использованием свойств:

Namespace tui
    Type Point
        Dim As Integer x, y
    End Type

    Type char
        Dim As UByte value
        Dim As UByte Color
    End Type

    Type Window
        '' public
        Declare Constructor _
            ( _
                x As Integer = 1, y As Integer = 1, _
                w As Integer = 20, h As Integer = 5, _
                title As ZString Ptr = 0 _
            )
        
        Declare Destructor

        Declare Sub show

        '' свойства для названия
        Declare Property title As String
        Declare Property title( new_title As String )

        '' свойства для позиции
        Declare Property x As Integer
        Declare Property x( new_x As Integer )

        Declare Property y As Integer
        Declare Property y( new_y As Integer )

    Private:
        Declare Sub redraw
        Declare Sub remove
        Declare Sub drawtitle

        Dim As String p_title
        Dim As Point Pos
        Dim As Point siz
    End Type

    Constructor Window _
        ( _
            x_ As Integer, y_ As Integer, _
            w_ As Integer, h_ As Integer, _
            title_ As ZString Ptr _
        )

        pos.x = x_
        pos.y = y_
        siz.x = w_
        siz.y = h_

        If( title_ = 0 ) Then
            title_ = @"untitled"
        End If

        p_title = *title_
    End Constructor

    Destructor Window
        Color 7, 0
        Cls
    End Destructor

    Property window.title As String
        title = p_title
    End Property

    Property window.title( new_title As String )
        p_title = new_title
        drawtitle
    End Property

    Property window.x As Integer
        Return pos.x
    End Property

    Property window.x( new_x As Integer )
        remove
        pos.x = new_x
        redraw
    End Property

    Property window.y As Integer
        Property = pos.y
    End Property

    Property window.y( new_y As Integer )
        remove
        pos.y = new_y
        redraw
    End Property

    Sub window.show
        redraw
    End Sub

    Sub window.drawtitle
        Locate pos.y, pos.x
        Color 15, 1
        Print Space( siz.x );
        Locate pos.y, pos.x + (siz.x \ 2) - (Len( p_title ) \ 2)
        Print p_title;
    End Sub

    Sub window.remove
        Color 0, 0
        Var sp = Space( siz.x )
        For i As Integer = pos.y To pos.y + siz.y - 1
            Locate i, pos.x
            Print sp;
        Next
    End Sub

    Sub window.redraw
        drawtitle
        Color 8, 7
        Var sp = Space( siz.x )
        For i As Integer = pos.y + 1 To pos.y + siz.y - 1
            Locate i, pos.x
            Print sp;
        Next
    End Sub
End Namespace

Dim win As tui.window = tui.window( 3, 5, 50, 15 )

win.show
Sleep 500

win.title = "Window 1"
Sleep 250
win.x = win.x + 10
Sleep 250

win.title = "Window 2"
Sleep 250
win.y = win.y - 2
Sleep 250

Locate 25, 1
Color 7, 0
Print "Press any key...";

Sleep


Обратите внимание, как при обновлении позиции окна или названия, автоматически окно перерисовывается.

Индексированные свойства


Свойства могут иметь дополнительный параметр, который называется индексом (в настоящее время только один дополнительный параметр разрешен). Индекс указывается в круглых скобках за именем свойства, как если бы свойство было массивом (с одним измерением). Например:

Type IntArray
    '' setters
    Declare Property value(index As Integer, v As Integer)
    Declare Property value(index As String, v As Integer)
    Declare Property value(index As Integer, v As String)
    Declare Property value(index As String, v As String)

    '' getters
    Declare Property value(index As Integer) As Integer
    Declare Property value(index As String) As Integer

Private:
    Dim As Integer data_(0 To 9)
End Type

Property IntArray.value(index As Integer) As Integer
    Return This.data_(index)
End Property

Property IntArray.value(index As String) As Integer
    Return This.data_(CInt(index))
End Property

Property IntArray.value(index As Integer, v As Integer)
    This.data_(index) = v
End Property

Property IntArray.value(index As String, v As Integer)
    This.data_(CInt(index)) = v
End Property

Property IntArray.value(index As Integer, v As String)
    This.data_(index) = CInt(v)
End Property

Property IntArray.value(index As String, v As String)
    This.data_(CInt(index)) = CInt(v)
End Property

Dim a As IntArray

a.value(0) = 1234
a.value("1") = 5678
a.value(2) = "-1234"
a.value("3") = "-5678"

Print a.value(0)
Print a.value("1")
Print a.value(2)
Print a.value("3")

Sleep

Это имитирует массив целых чисел, в который можно назначить строки, и даже сами индексы могут быть строковыми. Смотрите другой пример KeyPgProperty.