Spec-Zone.ru › Tcl/Tk

class

ИМЯ
itcl::class — создание класса объектов
СИНТАКСИС
ОПИСАНИЕ
ОПРЕДЕЛЕНИЯ КЛАССОВ
class имяКласса определение
inherit базовыйКласс ?базовыйКласс...?
constructor аргументы ?инициализация? код
destructor код
method имя ?аргументы? ?код?
proc имя ?аргументы? ?код?
variable имяПеременной ?инициализация? ?конфигурация?
common имяПеременной ?инициализация?
public команда ?арг арг ...?
protected команда ?арг арг ...?
private команда ?арг арг ...?
ИСПОЛЬЗОВАНИЕ КЛАССОВ
имяКласса имяОбъекта ?арг...?
ИСПОЛЬЗОВАНИЕ ОБЪЕКТОВ
имяОбъекта метод ?арг...?
ВСТРОЕННЫЕ МЕТОДЫ
имяОбъекта cget опция
имяОбъекта configure ?опция? ?значение опция значение ...?
имяОбъекта isa имяКласса
имяОбъекта info опция ?арг...?
имяОбъекта info class
имяОбъекта info inherit
имяОбъекта info heritage
имяОбъекта info function ?имяКоманды? ?-protection? ?-type? ?-name? ?-args? ?-body?
имяОбъекта info variable ?имяПеременной? ?-protection? ?-type? ?-name? ?-init? ?-value? ?-config?
ЦЕПОВЫЕ МЕТОДЫ/ПРОЦЕДУРЫ
АВТОЗАГРУЗКА
C ПРОЦЕДУРЫ
КЛЮЧЕВЫЕ СЛОВА

Имя

itcl::class — создание класса объектов

Синтаксис

itcl::class имяКласса {
inherit базовыйКласс ?базовыйКласс...?
constructor аргументы ?инициализация? код
destructor код
method имя ?аргументы? ?код?
proc имя ?аргументы? ?код?
variable имяПеременной ?инициализация? ?конфигурация?
common имяПеременной ?инициализация?

public команда ?арг арг ...?
protected команда ?арг арг ...?
private команда ?арг арг ...?

set имяПеременной ?значение?
array опция ?арг арг ...?
}

имяКласса имяОбъекта ?арг арг ...?

имяОбъекта метод ?арг арг ...?

имяКласса::proc ?арг арг ...?

Описание

Основным элементом в [incr Tcl] является определение класса. Каждый класс служит шаблоном для создания фактических объектов. Сам класс — это пространство имён, содержащее общие для всех объектов элементы. Каждый объект имеет свой собственный набор данных, содержащий экземпляры "переменных", определённых в определении класса. Каждый объект также имеет встроенную переменную "this", которая содержит имя объекта. Классы также могут иметь "общие" члены данных, которые разделяются всеми объектами в классе.

В определение класса можно включать два типа функций. "Методы" — это функции, которые работают с конкретным объектом и, следовательно, имеют доступ к "переменным" и "общим" членам данных. "Процедуры" — это обычные процедуры в пространстве имён класса, и они имеют доступ только к "общим" членам данных.

Если тело любого метода или процедуры начинается с "@", оно обрабатывается как символическое имя C-процедуры. В противном случае оно обрабатывается как скрипт кода Tcl. Более подробную информацию о регистрации и использовании C-процедур см. ниже.

Класс может быть определён только один раз, хотя тела методов и процедур класса могут быть определены снова и снова для интерактивной отладки. Подробности см. в командах body и configbody.

Каждое пространство имён может иметь свою коллекцию объектов и классов. Список доступных классов в текущем контексте можно запросить с помощью команды "itcl::find classes", а список объектов — с помощью команды "itcl::find objects".

Класс можно удалить с помощью команды "delete class". Отдельные объекты можно удалить с помощью команды "delete object".

Определения классов

class имяКласса определение
Предоставляет определение класса с именем имяКласса. Если класс имяКласса уже существует или если команда с именем имяКласса существует в текущем контексте пространства имён, эта команда возвращает ошибку. Если определение класса успешно обработано, имяКласса становится командой в текущем контексте, обрабатывающей создание объектов для этого класса.

Определение класса определение оценивается как серия команд Tcl, которые определяют элементы в классе. Распознаются следующие команды определения класса:

у наследства baseClass ?baseClass...?
Заставляет текущий класс унаследовать характеристики от одного или нескольких базовых классов. Классы должны быть определены предыдущей командой class или должны быть доступны для механизма автоматической загрузки (см. "АВТОЗАГРУЗКА" ниже). Определение одного класса может содержать не более одной команды inherit.

Порядок имен baseClass в списке inherit влияет на разрешение имен для членов класса. Если одно и то же имя члена встречается в двух или более базовых классах, базовый класс, который появляется первым в списке inherit, имеет приоритет. Например, если классы "Foo" и "Bar" оба содержат член "x", и если другой класс имеет оператор inherit:

inherit Foo Bar

то имя "x" означает "Foo::x". Другие унаследованные члены с именем "x" должны быть указаны с их явным именем, например, "Bar::x".

конструктор args ?init? body
Объявляет список аргументов args и body, используемые для конструктора, который автоматически вызывается всякий раз, когда создается объект.

Перед выполнением body необязательное выражение init используется для вызова конструкторов базового класса, которые требуют аргументов. Переменные в спецификации args могут быть доступны в фрагменте кода init и переданы конструкторам базового класса. После вычисления выражения init любые конструкторы базовых классов, которые еще не были выполнены, вызываются автоматически без аргументов. Это гарантирует, что все базовые классы будут полностью сконструированы до выполнения тела конструктора body. По умолчанию эта схема вызывает конструкторы в порядке от наименее к наиболее специфическому. Это прямо противоположно порядку, в котором классы сообщаются командой info heritage.

В случае успешного построения конструктор всегда возвращает имя объекта — независимо от того, как определен body — и имя объекта становится командой в текущем контексте пространства имен. В случае неудачи возвращается сообщение об ошибке.

деструктор body
Объявляет body, используемый для деструктора, который автоматически вызывается при удалении объекта. Если деструктор выполняется успешно, данные объекта уничтожаются, а имя объекта удаляется как команда из интерпретатора. Если разрушение завершилось ошибкой, возвращается сообщение об ошибке, и объект остается.

При уничтожении объекта все деструкторы в его иерархии классов вызываются в порядке от наиболее к наименее специфическому. Это порядок, в котором классы сообщаются командой «info heritage», и это прямо противоположно порядку вызова конструкторов по умолчанию.

метод name ?args? ?body?
Объявляет метод с именем name. При выполнении метода body он будет иметь автоматический доступ к объектно-специфическим переменным и общим данным.

Если указан список args, он устанавливает информацию об использовании этого метода. Команда body может быть использована для переопределения тела метода, но список args должен соответствовать этой спецификации.

Внутри тела другого метода класса метод может быть вызван как любая другая команда — просто указав его имя. Вне контекста класса имя метода должно предваряться именем объекта, который предоставляет контекст для данных, которые он обрабатывает. Методы базового класса, которые переопределены в текущем классе или скрыты другим базовым классом, могут быть квалифицированы с помощью синтаксиса "className::method".

процедура name ?args? ?body?
Объявляет процедуру с именем name. Процедура — это обычная процедура в пространстве имен класса. В отличие от метода, процедура вызывается без ссылки на конкретный объект. При выполнении тела процедуры body она будет иметь автоматический доступ только к общим данным.

Если указан список args, он устанавливает информацию об использовании этой процедуры. Команда body может быть использована для переопределения тела процедуры, но список args должен соответствовать этой спецификации.

Внутри тела другого метода класса или процедуры процедура может быть вызвана как любая другая команда — просто указав её имя. В любом другом контексте пространства имен процедура вызывается с помощью квалифицированного имени, например, «className::proc». Процедуры базового класса, которые переопределены в текущем классе или скрыты другим базовым классом, также могут быть доступны по их квалифицированному имени.

переменная varName ?init? ?config?
Определяет объектно-специфическую переменную с именем varName. Все объектно-специфические переменные автоматически доступны в методах класса. Их не нужно объявлять с чем-либо, подобным команде global.

Если указана необязательная строка init, она используется в качестве начального значения переменной при создании нового объекта. Инициализация принудительно устанавливает переменную как простую скалярную величину; неинициализированные переменные, с другой стороны, могут быть установлены внутри конструктора и использоваться как массивы.

Необязательный скрипт config разрешен только для публичных переменных. Если он указан, этот фрагмент кода выполняется всякий раз, когда встроенный метод "configure" изменяет публичную переменную. Скрипт config также может быть указан вне определения класса с помощью команды configbody.

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

Если указана необязательная строка init, она используется в качестве начального значения переменной. Инициализация принудительно устанавливает переменную как простую скалярную величину; неинициализированные переменные, с другой стороны, могут быть установлены с помощью последующих команд set и array и использоваться как массивы.

После определения общей переменной её можно установить с помощью команд set и array внутри определения класса. Это позволяет инициализировать общие переменные как массивы. Например:

itcl::class Foo {
    common boolean
    set boolean(true) 1
    set boolean(false) 0
}

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

публичный command ?arg arg ...?
защищенный command ?arg arg ...?
приватный command ?arg arg ...?
Эти команды используются для установки уровня защиты для членов класса, которые создаются при вычислении command. command обычно является методом, процедурой, переменной или общей, а оставшиеся arg завершают определение члена. Однако command также может быть скриптом, содержащим множество различных определений членов, и уровень защиты будет применяться ко всем членам, которые создаются.

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

После определения класса имя класса может использоваться как команда для создания новых объектов, принадлежащих классу.
className objName ?args...?
Создает новый объект в классе className с именем objName. Остальные аргументы передаются в конструктор класса с наибольшей специфичностью. Это, в свою очередь, передаёт аргументы конструкторам базовых классов перед вызовом собственного тела команд. В случае успешного построения создается команда с именем objName в текущем контексте пространства имен, и objName возвращается как результат этой операции. При возникновении ошибки во время построения деструкторы автоматически вызываются для освобождения любых выделенных ресурсов, объект удаляется, и возвращается ошибка.

Если objName содержит строку "#auto", эта строка заменяется автоматически сгенерированным именем. Имена имеют вид className<number>, где часть className модифицируется так, чтобы начинаться с маленькой буквы. Например, в классе "Toaster" спецификация "#auto" создаст имена, такие как toaster0, toaster1 и т. д. Обратите внимание, что "#auto" может также быть скрыто внутри имени объекта:

fileselectiondialog .foo.bar.#auto -background red

Это создаст объект с именем ".foo.bar.fileselectiondialog0".

Использование объекта

После создания объекта имя объекта можно использовать как команду для вызова методов, которые работают с объектом.
objName method ?args...?
Вызывает метод с именем method для объекта с именем objName. Остальные аргументы передаются в список аргументов для метода. Имя метода может быть "конструктор", "деструктор", любое имя метода, появляющееся в определении класса, или любой из следующих встроенных методов.

Встроенные методы

objName cget option
Предоставляет доступ к общедоступным переменным в качестве параметров конфигурации. Это имитирует поведение обычной операции "cget" для виджетов Tk. Аргумент option представляет собой строку вида "-varName", и этот метод возвращает текущее значение общедоступной переменной varName.
objName configure ?option? ?value option value ...?
Предоставляет доступ к общедоступным переменным в качестве параметров конфигурации. Это имитирует поведение обычной операции "configure" для виджетов Tk. Без аргументов этот метод возвращает список списков, описывающих все общедоступные переменные. Каждый список содержит три элемента: имя переменной, её начальное значение и текущее значение.

Если указан единственный параметр option вида "-varName", то этот метод возвращает информацию об этой переменной.

В противном случае аргументы обрабатываются как пары option/value, назначающие новые значения общедоступным переменным. Каждой переменной присваивается новое значение, и если у неё есть связанный код "config", он выполняется в контексте класса, где он был определён. Если код "config" генерирует ошибку, переменная возвращается к предыдущему значению, и метод configure возвращает ошибку.

objName isa className
Возвращает ненулевое значение, если заданный className найден в иерархии объекта, и ноль в противном случае.
objName info option ?args...?
Возвращает информацию, относящуюся к конкретному объекту с именем objName или к определению его класса. Параметр option включает следующие элементы, а также параметры, распознаваемые обычной командой Tcl "info":
objName info class
Возвращает имя наиболее конкретного класса для объекта objName.
objName info inherit
Возвращает список базовых классов, как они были определены в команде "inherit", или пустую строку, если у этого класса нет базовых классов.
objName info heritage
Возвращает текущее имя класса и весь список базовых классов в порядке, в котором они просматриваются для поиска членов и уничтожения объектов.
objName info function ?cmdName? ?-protection? ?-type? ?-name? ?-args? ?-body?
Без аргументов эта команда возвращает список всех методов и процедур класса. Если указан cmdName, она возвращает информацию для определённого метода или процедуры. Если не указаны флаги, эта команда возвращает список с такими элементами: уровень защиты, тип (метод/процедура), полное имя, список аргументов и тело. Флаги могут быть использованы для запроса конкретных элементов из этого списка.
objName info variable ?varName? ?-protection? ?-type? ?-name? ?-init? ?-value? ?-config?
Без аргументов эта команда возвращает список всех переменных, специфичных для объекта, и общих данных. Если указан varName, она возвращает информацию о конкретной переменной. Если не указаны флаги, эта команда возвращает список с такими элементами: уровень защиты, тип (переменная/общая), полное имя, начальное значение и текущее значение. Если varName — это общедоступная переменная, код "config" включается в этот список. Флаги могут быть использованы для запроса конкретных элементов из этого списка.

Цепочки методов/процедур

Иногда базовый класс имеет метод или процедуру, которая переопределяется с тем же именем в производном классе. Это способ заставить производный класс обрабатывать те же операции, что и базовый класс, но со своей специализированной обработкой. Например, предположим, что у нас есть класс Toaster, который выглядит так:
itcl::class Toaster {
    variable crumbs 0
    method toast {nslices} {
        if {$crumbs > 50} {
            error "== FIRE! FIRE! =="
        }
        set crumbs [expr $crumbs+4*$nslices]
    }
    method clean {} {
        set crumbs 0
    }
}

Мы можем создать другой класс, например, SmartToaster, который переопределяет метод "toast". Если мы хотим получить доступ к методу базового класса, мы можем квалифицировать его именем базового класса, чтобы избежать неоднозначности:

itcl::class SmartToaster {
    inherit Toaster
    method toast {nslices} {
        if {$crumbs > 40} {
            clean
        }
        return [Toaster::toast $nslices]
    }
}

Вместо жёсткого кодирования имени базового класса, мы можем использовать команду "chain" следующим образом:

itcl::class SmartToaster {
    inherit Toaster
    method toast {nslices} {
        if {$crumbs > 40} {
            clean
        }
        return [chain $nslices]
    }
}

Команда chain ищет в иерархии классов реализацию метода или процедуры, которая немного более общая (базовый класс), и вызывает её со специфицированными аргументами. Она начинается с текущего контекста класса и ищет в базовых классах в порядке, который сообщается командой "info heritage". Если другая реализация не найдена, эта команда ничего не делает и возвращает пустую строку.

Автозагрузка

Определения классов не обязательно должны загружаться явно; они могут загружаться по мере необходимости стандартными средствами автозагрузки Tcl. Каждый каталог, содержащий файлы определений классов, должен иметь соответствующий файл "tclIndex". Каждая строка в этом файле идентифицирует Tcl процедуру или определение класса [incr Tcl] и файл, где определение можно найти.

Например, предположим, что каталог содержит определения для классов "Toaster" и "SmartToaster". Тогда файл "tclIndex" для этого каталога будет выглядеть так:

# Tcl autoload index file, version 2.0 for [incr Tcl]
# This file is generated by the "auto_mkindex" command
# and sourced to set up indexing information for one or
# more commands.  Typically each line is a command that
# sets an element in the auto_index array, where the
# element name is the name of a command and the value is
# a script that loads the command.

set auto_index(::Toaster) "source $dir/Toaster.itcl"
set auto_index(::SmartToaster) "source $dir/SmartToaster.itcl"

Команда auto_mkindex используется для автоматического генерирования файлов "tclIndex".

Автозагрузчик должен знать об этом каталоге, добавив имя каталога в переменную "auto_path". Когда это сделано, классы будут автоматически загружаться по мере необходимости при использовании в приложении.

C-процедуры

C-процедуры могут быть интегрированы в определение класса [incr Tcl] для реализации методов, процедур и кода "config" для общедоступных переменных. Любое тело, начинающееся с "@", обрабатывается как символическое имя C-процедуры.

Символические имена устанавливаются путём регистрации процедур через Itcl_RegisterC(). Это обычно делается в процедуре Tcl_AppInit(), которая автоматически вызывается при запуске интерпретатора. В следующем примере процедура My_FooCmd() регистрируется под символическим именем "foo". Эта процедура может быть указана в команде body как "@foo".

int
Tcl_AppInit(interp)
    Tcl_Interp *interp;     /* Interpreter for application. */
{
    if (Itcl_Init(interp) == TCL_ERROR) {
        return TCL_ERROR;
    }

    if (Itcl_RegisterC(interp, "foo", My_FooCmd) != TCL_OK) {
        return TCL_ERROR;
    }
}

C-процедуры реализуются так же, как и обычные Tcl команды. Смотрите руководство по CrtCommand для получения подробностей. Внутри процедуры, члены данных класса могут быть доступны как обычные переменные с помощью Tcl_SetVar(), Tcl_GetVar(), Tcl_TraceVar() и т. д. Методы и процедуры класса могут быть выполнены как обычные команды с помощью Tcl_Eval(). [incr Tcl] делает это возможным, автоматически настраивая контекст перед выполнением C-процедуры.

Эта схема обеспечивает естественный путь миграции для разработки кода. Классы могут быть разработаны быстро с помощью Tcl кода для реализации тел. Весь проект может быть построен и протестирован. При необходимости отдельные тела могут быть реализованы на C для повышения производительности.

Licensed under Tcl/Tk terms
https://www.tcl.tk/man/tcl/ItclCmd/class.htm

Licensed under Tcl/Tk terms
https://www.tcl.tk/man/tcl/ItclCmd/class.htm

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API