Spec-Zone.ru › Tcl/Tk

itclextendedclass

ИМЯ
itcl::extendedclass — создание расширенного класса объектов
ПРЕДУПРЕЖДЕНИЕ!
СИНТАКСИС
ОПИСАНИЕ
ОПРЕДЕЛЕНИЯ КЛАССОВ
extendedclass extendedclassName определение
inherit baseExtendedclass ?baseExtendedclass...?
constructor args ?init? body
destructor body
method name ?args? ?body?
proc name ?args? ?body?
variable varName ?init? ?config?
common varName ?init?
public command ?arg arg ...?
protected command ?arg arg ...?
private command ?arg arg ...?
ИСПОЛЬЗОВАНИЕ КЛАССОВ
extendedclassName objName ?args...?
ИСПОЛЬЗОВАНИЕ ОБЪЕКТОВ
objName method ?args...?
ВСТРОЕННЫЕ МЕТОДЫ
objName cget option
objName configure ?option? ?value option value ...?
objName isa extendedclassName
objName info option ?args...?
objName info extendedclass
objName info inherit
objName info heritage
objName info function ?cmdName? ?-protection? ?-type? ?-name? ?-args? ?-body?
objName info variable ?varName? ?-protection? ?-type? ?-name? ?-init? ?-value? ?-config?
МЕТОДЫ/ПРОЦЕДУРЫ ЦЕПОЧКИ
АВТОЗАГРУЗКА
C-ПРОЦЕДУРЫ
КЛЮЧЕВЫЕ СЛОВА

Имя

itcl::extendedclass — создание расширенного класса объектов

Предупреждение!

Это новая функциональность в [incr Tcl], где API может быть изменён!!

Синтаксис

itcl::extendedclass extendedclassName{
inherit baseExtendedclass ?baseExtendedclass...?
constructor args ?init? body
destructor body
public method name ?args? ?body?
protected method name ?args? ?body?
private method name ?args? ?body?
public proc name ?args? ?body?
protected proc name ?args? ?body?
private proc name ?args? ?body?
public variable varName ?init? ?config?
protected variable varName ?init? ?config?
private variable varName ?init? ?config?
public common varName ?init?
protected common varName ?init?
private common varName ?init?

public command ?arg arg ...?
protected command ?arg arg ...?
private command ?arg arg ...?

<информация о делегировании> см. страницу делегирования

<информация об опциях> см. страницу опций

set varName ?value?
array option ?arg arg ...?
}

extendedclassName objName ?arg arg ...?

objName method ?arg arg ...?

extendedclassName::proc ?arg arg ...?

Описание

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

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

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

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

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

Расширенный класс может быть удалён с помощью команды «delete extendedclass». Отдельные объекты могут быть удалены с помощью команды «delete object».

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

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

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

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

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

inherit Foo Bar

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

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

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

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

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

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

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

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

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

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

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

Внутри тела метода или процедуры другого расширенного класса процедуру можно вызвать как любую другую команду — просто используя ее имя. В любом другом контексте пространства имен процедура вызывается с помощью квалифицированного имени, например, "extendedclassName::proc". Процедуры в базовом расширенном классе, которые переопределяются в текущем расширенном классе или скрываются другим базовым расширенным классом, также могут быть доступны через свое квалифицированное имя.

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

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

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

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

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

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

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

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

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

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

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

Если objName содержит строку «#auto», эта строка заменяется автоматически сгенерированным именем. Имена имеют вид extendedclassName<number>, где часть extendedclassName модифицируется так, чтобы начинаться с маленькой буквы. Например, в расширенном классе «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 extendedclassName
Возвращает ненулевое значение, если заданный extendedclassName можно найти в родословной объекта, и ноль в противном случае.
objName info option ?args...?
Возвращает информацию, относящуюся к конкретному объекту с именем objName или к определению его расширенного класса. Параметр option включает в себя следующие элементы, а также опции, распознаваемые обычной командой Tcl «info»:
objName info extendedclass
Возвращает имя наиболее конкретного расширенного класса для объекта 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::extendedclass 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::extendedclass SmartToaster {
    inherit Toaster
    method toast {nslices} {
        if {$crumbs > 40} {
            clean
        }
        return [Toaster::toast $nslices]
    }
}

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

itcl::extendedclass 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/itclextendedclass.htm

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

Spec-Zone.ru

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