Smalltalk по-русски
Advertisement
16.0

Протокол Классов[]

16.diagramma

Сейчас введён протокол для большинства классов системы которые описывают основные компоненты системы Смолток. Одним значительным исключением является протокол для самих классов. Четыре класса: Поведение, Описание класса, Метакласс и Класс - вместе предоставляют средства для описания новых классов. Создание нового класса включает компиляцию методов и задание имён для переменных экземпляра, переменных класса, переменных пула и для самого класса.

В главах 3, 4 и 5 были введены основные концепции представляемые этими классами. Подводя итог можно сказать что Смолток программист задаёт новый класс путём создания подкласса другого класса. Например, класс Набор это подкласс Объекта; класс Ряд это подкласс Набора ряда (чья цепь наследования заканчивается Объектом).

1. Каждый класс в конечном счёте является подклассом Объекта, за исключением самого Объекта, у которого нету суперкласса. В частности, Класс это подкласс Описания класса, который является подклассом Поведения который является подклассом Объекта.

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

2. Каждый объект это экземпляр класса.

Каждый класс сам является экземпляром класса. Класс класса называется его метаклассом.

3. Каждый класс это экземпляр метакласса.

На метакласс нельзя сослаться по имени как на другие классы. Вместо этого на них ссылаются при помощи унарного сообщения класс посылаемого экземпляру метакласса. Например, на метакласс Набора ссылаются так: Набор класс; ссылка на метакласс Класса это Класс класс.

В системе Смолток при создании нового класса автоматически создаётся метакласс. У метакласса имеется только один экземпляр. Методы из категории "методы класса", в описании класса, находятся в метаклассе класса. Это следует из способа которым ищутся методы; когда сообщение посылается объекту, то поиск соответствующего метода начинается в классе объекта. Например, когда сообщение посылается Словарю, то поиск начинается в метаклассе Словаря. Если метод не находится в метаклассе, то поиск продолжается в суперклассе метакласса. В данном случае суперкласс это Множество класс, метакласс суперкласса Словаря. Если требуется, то поиск продолжается по цепи наследования вплоть до метакласса Объект класс.

В диаграммах этой главы все стрелки со сплошными линиями означают отношение подкласса; стрелки со штриховыми линиями это отношение экземпляра. A ---> B означает что A это экземпляр B. Сплошные серые линии указывают ирархию классов; сплошные чёрные линии указывают ирархию метаклассов.

16

Рисунок 16.1

Т.к. цепь суперклассов всех объектов заканчивается Объектом, как показано на рисунке 16.1, и у Объекта нету суперкласса, то суперкласс метакласса Объекта не определяется правилом поддержания параллельной ирархии. В этом месте появляется Класс. Суперкласс метакласса Объект класс это Класс.

4. Все метаклассы (в конце концов) это подклассы Класса (рисунок 16.2).

16

Рисунок 16.2

Т.к. метаклассы это объекты, то они должны быть экземплярами класса. Каждый метакласс это экземпляр Метакласса. Сам Метакласс это экземпляр метакласса. Это место зацикливания системы - метакласс Метакласса должен быть экземпляром Метакласса.

5. Каждый метакласс это экземпляр Метакласса (рисунок 16.3).

Рисунок 16.4 показывает взаимоотношения между Классом, Описанием класса, Поведением и Объектом, и соответствующих им метаклассов. Ирархия классов идёт до Объекта, а ирархия метаклассов следует через Объект класс до Класса и до Объекта. В то время как методы Объекта поддерживают поведение общее для всех объектов, методы Класса и Метакласса поддерживают поведение общее для всех классов.

16

Рисунок 16.3

6. Методы Класса и его суперклассов поддерживают поведение общее для тех объектов которые являются классами.

7. Методы экземпляров Метакласса добавляют поведение специфичное для отдельного класса.

Соответствие между ирархиями классов и метаклассов показано на рисунке 16.5.

16

Рисунок 16.4

16

Рисунок 16.5

Класс Поведение[]

Класс Поведение определяет минимальное состояние необходимое объектам у которых есть экземпляры. В частности, Поведение определяет состояние используемое интерпретатором Смолтока. Он предоставляет основной интерфейс компилятору. Состояние описываемое Поведением включает связь ирархии классов, словарь методов и описание экземпляров в терминах количества и представления их переменных.

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

Наборосок протокола всех классов

создание

  • создание словаря методов
  • создание экземпляров
  • создание ирархии классов

доступ

  • доступ к содержимому словаря методов
  • доступ к экземплярам и переменным: экземпляра, класса и пула
  • доступ к ирархии класса

проверки

  • проверка содержимого словаря методов
  • проверка формы экземпляров
  • проверка ирархии класса

перебор

  • перебор подклассов и экземпляров

Протокол создание класса Поведение[]

Методы в описании класса хранятся в словаре с именем словарь методов. Ионогда, он также называется словарь сообщений. Ключями этого словаря являются селектры; значения это откомпилированная форма методов (экземпляры Откомпилированного метода). Протокол создания словаря методов поддерживает компиляцию методов и также добавление ассоциации между селектором и откомпилированным методом. Также поддерживается доступ и к откомпилированным и не откомпилированным (исходным) версиям методов.

Протокол экземпляров Поведения
создание словаря методов
словарь методов: словарь Запоминает аргумент, словарь, в качестве словаря методов получателя.
добавить селектор: селектор с методом: откомпилированный метод Добавляет селектор сообщения, селектор, с соответствующим откомпилированным методом, откомпилированный метод, в словарь методов получателя.
удалить селектор: селектор Удаляет аргумент, селектор (который является Символом представляющим селектор сообщения), из словаря методов получателя. Если селектора нету в словаре методов, то сообщается об ошибке.
компилировать: текст Аргумент, текст, это либо Цепь либо объект который можно преобразовать в Цепь либо это Позиционируемый поток для доступа к объекту являющемуся Цепью. Компилирует текст как исходный текст в контексте переменных получателя. Сообщает об ошибке если текст не может быть скомпилирован.
компилировать: текст уведомлять: запрощик Компилирует аргумент, текст, и вставляет результат в словарь методов получателя. Если происходит ошибка, то посылает соответствующее сообщение аргументу, запрощик.
перекомпилировать: селектор Компилирует метод связанный с селектором сообщения, селектор.
декомпилировать: селектор Находит откомпилированный код связанный с аргументом, селектор, и декомпилирует его. Возвращает полученный исходный текст в виде Цепи. Если селектора нету в словаре методов, то сообщается об ошибке.
компилировать весь Компилирует все методы из словаря методов получателя.

Экземпляры классов создаются при помощи посылки сообщений новый или новый:. Эти два сообщения могут быть переопределены в словаре методов метакласса для добавления особого поведения инициализации. Назначение любого особого инициализирования в том чтобы гарантировать что экземпляр создастся с переменными которым присвоены соответствующие экземпляры. Эта идея была продемонстрирована во всех предыдущих главах.

Допустим класс переопределяет метод новый и затем один из его подклассов хочет сделать то же так чтобы избежать изменения поведения своего суперкласса. Метод из первого класса может быть таким:

новый
   супер новый присвоить переменные.

где сообщение присвоить переменные предоставляется протоколом экземпляра этого класса. При посылке сообщения новый псевдо переменной супер вызывается метод создания экземпляра заданный в классе Поведение; затем результату, новому экземпляру, посылается сообщение присвоить переменные. В подклассе нельзя использовать сообщение супер новый чтобы вызвать метод Поведения, т.к. оно вызовет метод первого класса. Чтобы вызвать основной метод создания экземпляра из Поведения, подкласс может использовать выражение сам основной новый. Сообщение основной новый это примитивное сообщение создания экземпляра которое не должно переопределяться ни каким подклассом. В Поведении и новый и основной новый идентичны. Поведением также предоставляется подобная пара сообщений новый: и основной новый: для создания объектов переменной длины. (Заметьте что техника двойных сообщения также используется в классе Объект для методов доступа от: и от:пом:.)

Протокол экземпляров Поведения
создание экземпляра
новый Возвращает экземпляр получателя без нумерованных переменных. Посылает получателю сообщение новый: 0 если получатель нумерованный.
основной новый Такой же как и новый, за исключением того что этот метод не должен переопределяться подклассами.
новый: целое Возвращает экземпляр получателя с количеством нумерованных переменных целое. Сообщает об ошибке если получатель не нумерованный.
основной новый: целое Такой же как и новый:, за исключением того что этот метод не должен переопределяться подклассами.

Протокол создания классов включает сообщения для помещения класса в ирархию классов системы. Т.к. ирархия линейна, то нужны только сообщения для задания суперкласса и добавления или удаления подклассов.

Протокол экземпляров Поведения
создание ирархии классов
суперкласс: класс Присваивает суперклассу получаетля аргумент, класс.
addSubclass: aClass Make the argument, aClass, be a subclass of the receiver.
removeSubclass: aClass Remove the argument, aClass, from the subclasses of the receiver.

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

Протокол доступ класса Поведение[]

Сообщения которые обращаются к содержимому словаря методов делятся на те которые служат для обращения к локальному словарю методов класса, и те которые служат для доступа к словарям методов класса и всех его суперклассов.

Протокол экземпляров Поведения
доступ к словарю методов
селекторы Возвращает Множество всех селекторов сообщений определённых в локальном словаре методов получателя.
все селекторы Возвращает Множество всех селекторов сообщений которые может понимать экземпляр получателя. Оно содержит все сообщения селекторов из словаря методов получателя и каждого из суперклассов получателя.
откомпилированный метод от: селектор Возвращает откомпилированный метод связанный с аргументом, селектор, селектором сообщения локального словаря методов получателя. Если селектор не найден, то сообщается об ошибке.
исходный текст от: селектор Возвращает Цепь которая является исходным текстом связанным с аргументом, селектор, селектором сообщения локального словаря методов получателя. Если селектор не найден, то сообщается об ошибке.
исходный метод от: селектор Возвращает Текст для исходного текста связанного с аргументом, селектор, селектором сообщения локального словаря методов получателя. Этот Текст содержит выделение жырным шрифтом образца сообщения. Если селектор не найден, то сообщается об ошибке.

У экземпляра может быть переменные экземпляра, нумерованные переменные экземпляра, переменные класса и словари переменных пула. Опять же, различие между локально заданными переменными и переменными унаследованными от суперклассов отражается в протоколе доступа.

'Протокол экземпляров Поведения'
доступ к экземплярам и переменным
все экземпляры Возвращает Множество всех прямых экземпляров получателя.
некоторый экземпляр Возвращает существующий экземпляр получателя.
количество экземпляров Возвращает количество существующих в данный момент экземпляров получателя.
имена переменных экземпляра Возвращает Ряд имён переменных экземпляра заданных в получателе.
имена переменных экземпляра подклассов Возвращает Множество имён переменных экземпляра заданных в подклассах получателя.
все имена переменных экземпляра Возвращает Ряд из имён переменных экземпляра получателя которые заданы в получателе и всех его суперклассах. Упорядочиние Ряда это порядок в котором переменные используются интерпретатором Смолтока.
имена переменных класса Возвращает Множество имён переменных класса заданных в получателе локально.
все имена переменных класса Возвращает Множество имён переменных класса заданных в получателе и его суперклассах.
разделяемые пулы Возвращает Множество имён пулов (словарей) которые заданы в получателе локально.
все разделяемые пулы Возвращает Множество имён пулов (словарей) которые заданы в получателе и каждом из его суперклассов.

Поэтому:

предложение результат
Упорядоченный набор имена переменных экземпляра. #('ряд' 'первый номер' 'последний номер')
Упорядоченный набор имена переменных экземпляра подклассов. #('сортирующий блок')
Сортированный набор все имена переменных экземпляра. #('ряд' 'первый номер' 'последний номер' 'сортирующий блок')
Текст разделяемые пулы. an OrderedCollection(a Dictionary(size 110))

Протокол доступа включает сообщения для получения наборов суперклассов и подклассов класса. Эти сообщения разделяются на две группы: непосредственные подклассы и суперклассы класса и все классы из цепи наследования класса.

Протокол экземпляров Поведения
доступ к ирархии классов
подклассы Возвращает Множество содержащие непосредственные подклассы получателя.
все подклассы Возвращает Множество содержащие подклассы получателя и их потомков.
со всеми подклассами Возвращает Множество из получателя, подклассов получателя и потомков подклассов получателя.
суперкласс Возвращает непосредственный суперкласс получателя.
все суперклассы Возвращает Упорядоченный набор суперклассов получателя. Первый элемент это непосредственный суперкласс получателя, затем идёт его суперкласс и т.д.; последний элемент это всег Прото объект.

Поэтому:

предложение результат
Цепь суперкласс. ArrayedCollection
Набор ряд подклассы. {DirectoryEntry . SoundBuffer . WordArray . RunArray . Array . ShortIntegerArray . Bitmap . FloatArray . Text . ShortRunArray . ByteArray . TranslatedMethod . IntegerArray . ColorArray . String . SparseLargeTable}
Набор ряд все подклассы. a Set(ShortRunArray PointArray WideSymbol ByteString Array Symbol ColorArray ByteArray FixedIdentitySet DependentsArray TTFIndexToLocation Bitmap KlattFrame QuickStack TranslatedMethod ShortIntegerArray Cubic WeakActionSequence CompiledMethod UUID WAExternalID WideString RunArray a subclass of String WeakActionSequenceTrappingErrors Text String SoundBuffer SparseLargeTable WordArrayForSegment ShortPointArray FloatArray ByteSymbol IntegerArray QuickIntegerDictionary DirectoryEntry WeakArray WordArray KedamaFloatArray ActionSequence)
Набор ряд со всеми подклассами. a Set(ShortRunArray PointArray WideSymbol ByteString Array Symbol ColorArray ByteArray FixedIdentitySet DependentsArray TTFIndexToLocation Bitmap KlattFrame QuickStack TranslatedMethod ShortIntegerArray Cubic WeakActionSequence CompiledMethod UUID WAExternalID WideString RunArray a subclass of String WeakActionSequenceTrappingErrors Text String SoundBuffer SparseLargeTable WordArrayForSegment ShortPointArray FloatArray ByteSymbol IntegerArray QuickIntegerDictionary DirectoryEntry ArrayedCollection WeakArray WordArray KedamaFloatArray ActionSequence)
Набор ряд все суперклассы. an OrderedCollection(SequenceableCollection Collection Object ProtoObject)
Набор ряд класс все суперклассы. an OrderedCollection(SequenceableCollection class Collection class Object class ProtoObject class Class ClassDescription Behavior Object ProtoObject)

Протокол проверок класса Поведение[]

Протокол проверок предоставляет сообщения служащие для нахождения информации о структуре класса и форме его экземпляров. Структура класса состоит из взаимоотношений с другими классами, его возможности отвечать на сообщения, класс в котором определено сообщения и т.д.

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

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

Thus, for example

expression result OrderedCoi lection true includesSelector: #addFirst: SortedCollection false includesSelector: #size SortedCollection true canUnderstand: #size SortedCollection OrderedCollection whichClasslncludesSelector: #size OrderedCollection Set whichSelectorsAccess: (makeRoomAtFirst

  1. firstlndex before: size

makeRoomAtLast insert:before: remove:ifAbsent: addFirst: first removeFirst find: removeAIISuchThat: at: atput: reverseDo: do: setlndices:)

The last example expression is useful in determining which methods must be changed if an instance variable is renamed or deleted. In addi- tion to the messages intended for external access, the Set includes all messages implemented in support of the implementation of the external messages.

The testing protocol includes messages to a class that test how its variables are stored, whether the number of variables is fixed-length or variable-length, and the number of named instance variables.

Behavior instance protocol testing the form of the instances isPointers Answer whether the variables of instances of the receiver are stored as pointers (words). isBitS Answer whether the variables of instances of the receiver are stored as bits (i.e., not pointers). isBytes Answer whether the variables of instances of the receiver are stored as bytes (8-bit integers). isWordS Answer whether the variables of instances of the receiver are stored as words. isFixed Answer true if instances of the receiver do not have indexed instance variables; answer false otherwise. isVariable Answer true if instances of the receiver do have indexed instance variables; answer false otherwise. instSize Answer the number of named instance vari- ables of the receiver.

So we have

expression result LinkedList isFixed true String isBytes true Integer isBits false Float isWords true OrderedCollection isFixed false OrderedCollection instSize 2 . oc <- OrderedCollection OrderedCollection with: Sa ($a $b $c ) with: $b with: $c oc size 3

The last four example lines show that instances of OrderedCollection are variable-length; the instance oc has three elements. In addition, instances of OrderedCollection have two named instance variables.

There are four kinds of classes in the system. Classes that have indexed instance variables are called variable-length and classes that do not are called fixed-length. The variables of all fixed-length classes are stored as pointers (word-sized references). The variables of variable-length classes can contain pointers, bytes, or words. Since a pointer is a word-sized reference, an object that contains pointers will answer true when asked whether it contains words, but the inverse is not always the case. Initialization messages specified in Class and itemized in a later section support creation of each kind of class.

Behavior instance protocol_________________________________________________________ testing the class hierarchy inheritsFrom: aClass Answer whether the argument, aClass, is on the receiver's superclass chain. kindOfSubclass Answer a String that is the keyword that de- scribes the receiver as a class: either a regular (fixed length) subclass, a variableSubclass, a variableByteSubclass, or a variableWord-Subclass.

Thus

expression result String inheritsFrom: Collection true String kindOfSubclass ' variableByteSubclass: ' Array kindOfSubclass ' variableSubclass: ' Float kindOfSubclass ' variabieWordSubclass: ' Integer kindOfSubclass ' subclass: '

Behavior's Enumerating Protocol[]

Messages specified in class Behavior also support listing out particular sets of objects associated with a class and applying each as the argument of a block. This enumeration of objects is similar to that provided in the collection classes, and consists of enumerating over all subclasses, superclasses, instances, and instances of subclasses. In addition, two messages support selecting those subclasses or superclasses for which a block evaluates to true.

Behavior instance protocol enumerating allSubclaSSesDo: aBlock Evaluate the argument, aBlock, for each of the receiver's subclasses. allSuperclassesDo: aBlock Evaluate the argument, aBlock, for each of the receiver's superclasses. alllnStancesDo: aBlock Evaluate the argument, aBlock, for each of the current instances of the receiver. allSubinstancesDo: aBlock Evaluate the argument, aBlock, for each of the current instances of the receiver's subclasses. selectSubclasses: aBlock Evaluate the argument, aBlock, for each of the receiver's subclasses. Collect into a Set only those subclasses for which aBlock evaluates to true. Answer the resulting Set. selectSuperclasses: aBlock Evaluate the argument, aBlock, with each of the receiver's superclasses. Collect into a Set only those superclasses for which aBlock evaluates to true. Answer the resulting Set.

As an example, in order to understand the behavior of an instance of the collection classes, it might be useful to know which subclasses of Collection implement the adding message addFirst:. With this information, the programmer can track down which method is actually evaluated when the message addFirst: is sent to a collection. The following expression collects each such class into a Set named subs.

subs — Set new. Collection allSubclassesDo: [ :class | (class inciudesSelector: #addFirst) ifTrue: [subs add: class]]

The same information is accessible from

Collection selectSubclasses: [ :class | class inciudesSelector: #addFirst]

Both create a Set of the three subclasses LinkedList, OrderedCollection, and RunArray.

The following expression returns a collection of the superclasses of Smalllnteger that implement the message =.

Smalllnteger selectSuperclasses: [ xlass ] class inciudesSelector: #=]

The response is

Set (Integer Magnitude Object)

Several subclasses of Collection implement the message first. Suppose we wish to see a list of the code for each implementation. The following expressions print the code on the file whose name is 'ciassfvlethods.first'.

I aStream | aStream <- Disk file: 'classMethods.first'. Collection allSubclassesDo: [ :class | (class includesSelector: #first) ifTrue: [class name printOn: aStream. aStream cr. (class sourceCodeAt: #first) printOn: aStream. aStream cr; cr]]. aStream close

The resulting contents of the file is

SequenceableCollection 'first self emptyCheck. T self at: V OrderedCollection 'first self emptyCheck. tself basicAt: firstlndex' Interval 'first t start' LinkedList 'first self emptyCheck. TfirstLink'

The protocol described in the next sections is not generally used by programmers, but may be of interest to system developers. The messages described are typically accessed in the programming environment by selecting items from a menu presented in a graphically-oriented interface.

Although most of the facilities of a class are specified in the protocol of Behavior, a number of the messages can not be implemented because Behavior does not provide a complete representation for a class. In particular, Behavior does not provide a representation for instance variable names and class variable names, nor for a class name and a comment about the class.

Representations for a class name, class comment, and instance variable names are provided in ClassDescription, a subclass of Behavior. ClassDescription has two subclasses, Class and Metaclass. Class de- scribes the representation for class variable names and pool variables. A metaclass shares the class and pool variables of its sole instance. Class adds additional protocol for adding and removing class variables and pool variables, and for creating the various kinds of subclasses. Metaclass adds an initialization message for creating a subclass of itself, that is, a message for creating a metaclass for a new class.

Class ClassDeSCription[]

ClassDescription represents class naming, class commenting, and naming instance variables. This is reflected in additional protocol for accessing the name and comment, and for adding and removing instance variables.

ClassDescription instance protocol accessing class description name Answer a String that is the name of the re- ceiver. comment Answer a String that is the comment for the receiver. comment: aString Set the receiver's comment to be the argu- ment, aString. addlnstVarName: aString Add the argument, aString, as one of the re- ceiver's instance variables. removelnstVarName: aString Remove the argument, aString, as one of the receiver's instance variables. Report an error if aString is not found.

ClassDescription was provided as a common superclass for Class and Metaclass in order to provide further structuring to the description of a class. This helps support a general program development environment. Specifically, ClassDescription adds structure for organizing the selector/method pairs of the method dictionary. This organization is a simple categorization scheme by which the subsets of the dictionary are grouped and named, precisely the way we have been grouping and naming messages throughout the chapters of this book. ClassDescription also provides the mechanisms for storing a full class description on an external stream (a file), and the mechanisms by which any changes to the class description are logged.

The classes themselves are also grouped into system category classifications. The organization of the chapters of this part of the book parallels that of the system class categories, for example, magnitudes, numbers, collections, kernel objects, kernel classes, and kernel support. Protocol for message and class categorization includes the following messages.

ClassDescription instance protocol____________________________________________ organization of messages and classes category Answer the system organization category for the receiver. category: aString Categorize the receiver under the system cate- gory, aString, removing the receiver from any previous category. removeCategory: aString Remove each of the messages categorized un- der the name aString and then remove the category itself. whichCategorylncludesSelector: selector Answer the category of the argument, selector, in the organization of the receiver's method dictionary, or answer nil if the selector can not be found.

Given a categorization of the messages, ClassDescription is able to support a set of messages for copying messages from one method dictionary to another, retaining or changing the category name. Messages to support copying consists of

copy: selector from: aClass copy: selector from: aClass classified: category Name copyAII: arrayOfSelectors from: class copyAII: arrayOfSelectors from: class classified: categoryName copyAIICategoriesFrom: aClass copyCategory: categoryName from: aClass copyCategory: categoryName from: aClass classified: newCategoryName

The categorization scheme has an impact on protocol for compiling since a compiled method must be placed in a particular category. Two messages are provided: compile: code classified: categoryName and compile: code classified: categoryName notifying: requestor.

We also note, for the next example, that Behavior supports special printing protocol so that arguments to the compiling messages can be computed. These are

Behavior instance protocol _________________________________________________ printing ClassVariableString Answer a String that contains the names of each class variable in the receiver's variable declaration. instanceVariableString Answer a String that contains the names of each instance variable in the receiver's variable declaration. sharedVariableString Answer a String that contains the names of each pool dictionary in the receiver's variable declaration.

Take as an example the creation of a class named AuditTrail. This class should be just like Linked List, except that removing elements should not be supported. Therefore, the class can be created by copying the accessing, testing, adding, and enumerating protocol of LinkedList. We assume that the elements of an AuditTrail are instances of a subclass of Link that supports storing the audit information. First, let's create the class. We assume that we do not know internal information about LinkedList so that the superclass name and variables must be accessed by sending messages to LinkedList.

LinkedList superclass subclass: #AuditTrail instanceVariableNames: LinkedList instanceVariableString classVariableNames: LinkedList classVariableString poolDictionaries: LinkedList sharedPoolString category: 'Record Keeping'.

AuditTrail is created as a subclass of whichever class is the superclass for LinkedList (LinkedList superclass). Now we copy the categories we are interested in from class LinkedList.

AuditTrail copyCategory: #accessing from: LinkedList. AuditTrail copyCategory: #testing from: LinkedList. AuditTrail copyCategory: #adding from: LinkedList. AuditTrail copyCategory: #enumerating from: LinkedList. AuditTrail copyCategory: #private from: LinkedList.

AuditTrail declared two instance variable names, firstLink and lastLink, and copied messages first, last, size, isEmpty, add:, addFirst, and addLast:. We also copied all the messages in the category private on the assumption that at least one of them is needed in the implementation of the external messages.

Some messages in ClassDescription that support storing the class description on an external stream are

ClassDescription instance protocol filing fileOutOn: aFileStream Store a description of the receiver on the file accessed by the argument, aFileStream. fileOutCategory: categoryName Create a file whose name is the name of the receiver concatenated by an extension, '.st'. Store on it a description of the messages categorized as categoryName. fileOutChangedMessages: setOfChanges on: aFileStream The argument, setOfChanges, is a collection of class/message pairs that were changed. Store a description of each of these pairs on the file accessed by the argument, aFileStream,

We can write a description of class AuditTrail on the file 'AuditTrail.st' by evaluating the expression

AuditTrail fileOutOn: (Disk file: 'AuditTrail.st')

Class MetaclaSS[]

The primary role of a metaclass in the Smalltalk-80 system is to pro- vide protocol for initializing class variables and for creating initialized instances of the metaclass's sole instance. Thus the key messages added by Metaclass are themselves initialization messages—one is sent to Metaclass itself in order to create a subclass of it, and one is sent to an instance of Metaclass in order to create its sole instance.

Metaclass class protocol instance creation SubclassOf: SUperMeta Answer an instance of Metaclass that is a sub- class of the metaclass, superMeta. name: newName environment: aSystemDictionary subclassOf: superclass instanceVariabieNames: stringOflnstVarNames variable: variableBoolean words: wordBoolean pointers: pointerBoolean classVariableNames: stringOfClassVarNames poolDictionaries: stringOfPoolNames category: categoryName comment: commentString changed: changed Each of these arguments, of course, is needed in order to create a fully initialized class.

The Smalltalk-80 programming environment provides a simplified way, using graphical interface techniques, in which the user specifies the information to create new classes.

Class Class[]

Instances of Class describe the representation and behavior of objects. Class adds more comprehensive programming support facilities to the basic ones provided in Behavior and more descriptive facilities to the ones provided in ClassDescription. In particular, Class adds the representation for class variable names and shared (pool) variables.

Class instance protocol accessing instances and variables addClassVarName: aString Add the argument, aString, as a class variable of the receiver. The first character of aString must be capitalized; aString can not already be a class variable name. removeClassVarName: aString Remove the receiver's class variable whose name is the argument, aString. Report an error if it is not a class variable or if it is still being used in a method of the class. addSharedPool: aDictionary Add the argument, aDictionary, as a pool of shared variables. Report an error if the dictionary is already a shared pool in the receiver. removeSharedPool: aDictionary Remove the argument, aDictionary, as one of the receiver's pool dictionaries. Report an error if the dictionary is not one of the receiver's pools. classPool Answer the dictionary of class variables of the receiver. initialize Initialize class variables.

Additional accessing messages store a description of the class on a file, where the file has the same name as that of the class (fileOut), and remove the class from the system (removeFromSystem).

A variety of messages for creating one of the four kinds of subclasses in the system are specified in the method dictionary of Class. In addition, Class provides a message for renaming a class (rename: aString); this message is provided in Class rather than in ClassDescription because it is not an appropriate message to send to a metaclass.

Class instance protocol instance creation subclass: classNameString instanceVariabieNames: stringlnstVarNames classVariableNames: stringOfClassVarNames pool Dictionaries: stringOfPoolNames category: categoryNameString Create a new class that is a fixed-length (regular) subclass of the receiver. Each of the arguments provides the information needed to initialize the new class and categorize it.

Three other messages, like the one above except that the first keyword is variableSubclass:, variableByteSubclass:, or variableWordSubclass, support the creation of the other kinds of classes. Note also that the system requires that a subclass of a variable-length class be a variable-length class. When possible, the system makes the appropriate conversion; otherwise, an error is reported to the programmer.

Suppose that every time we created a new subclass, we wanted to install messages for storing and retrieving the instance variables of that class. For example, if we create a class Record with instance variable names name and address, we wish to provide messages name and address, to respond with the values of these variables, and name: argument and address: argument, to set the values of these variables to the value of the message argument. One way to accomplish this is to add the following method to the instance creation protocol of class Class.

accessingSubclass: className instanceVariableNames: instVarString classVariableNames: classVarString poolDictionaries: stringOfPoolNames category: categoryName | newClass | newClass — self subclass: className instanceVariableNames: instVarString classVariableNames: classVarString poolDictionaries: stringOfPoolNames category: categoryName. newClass instVarNames do: [ :aName | newClass compile: (aName , ' T', aName) classified: #accessing. newClass compile: (aName , ': argument ', aName, ' - argument. Targument') classified: #accessing]. tnewClass

The method creates the class as usual, then, for each instance variable name, compiles two methods. The first is of the form

name tname

and the second is of the form

name: argument name - argument. targument

So, if we create the class Record, we can do so by sending Object the following message.

Object accessingSubclass: #Record instanceVariableNames: 'name address' classVariableNames: " poolDictionaries: " category: 'Example'.

The message is found in the method dictionary of Class, and creates the following four messages in the category accessing of class Record.

accessing name Tname name: argument name <- argument. targument address Taddress address: argument address «- argument. targument

Advertisement