Фэндом

Smalltalk по-русски

Смолток. Язык и его реализация/Вторая часть/14. Классы поддержки ядра

< Смолток. Язык и его реализация | Вторая часть

239статей на
этой вики
Добавить новую страницу
Обсуждение0 Поделиться
14.0.jpg

Классы поддержки ядраПравить

14.1.jpg

Класс Неопределённый объектПравить

Объект пусто является значением не инициализированных переменных. Также он представляет бессмысленный результат. Он является единственным экземпляром класса Неопределённый объект.

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

Имя класса не понимает селектора сообщения

где Имя класса указывает класс получателя и селектор сообщения это селектор неправильно посланного сообщения.

Заметьте что если бы пусто было экземпляром Объекта, то сообщение посланное ему вызвало бы сообщение

Объект не понимает селектора сообщения

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

Проверка на то является ли объект пусто осуществляется в классе Объект, но переопределена в Неопределённом объекте. В классе Объект, сообщение это пусто и не пусто реализованы как:

это пусто
   ложь.

не пусто
   истина.

В классе Неопределённый объект сообщения это пусто и не пусто реализованы как:

это пусто
   истина.

не пусто
   ложь.

Поэтому в Объекте не требуется проверка условия.

Классы Логика, Истина и ЛожьПравить

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

Логические операции это:

Протокол экземпляров Логики
логические операции
& логическое Вычисляет конъюнкцию. Возвращает истину если и получатель и аргумент это истина.
| логическое Вычисляет дизъюнкцию. Возвращает истину если либо получатель либо аргумент это истина.
не Отрицание. Возвращает истину если получатель это ложь, возвращает ложь если получатель это истина.
экв: логическое Возвращает истину если получатель эквивалентен аргументу, логическое.
и или: логическое Исключающее или. Возвращает истину если получатель не эквивалентен аргументу, логическое.

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

Протокол экземпляров Логики
управление
и: блок альтернатива Невычисляемая конъюнкция. Если получатель это истина, возвращается значение аргумента; иначе, возвращается ложь без вычисления аргумента.
или: блок альтернатива Невычисляемая дизъюнкцию. Если получатель это ложь, возвращается значение аргумента; иначе возвращается истина без вычисления аргумента.
истина: блок истина ложь: блок ложь Условное выражение. Если получатель это истина, возвращается результат выполнения блока истины; иначе возвращается результат выполнения блока лжи.
ложь: блок ложь истина: блок истина Условное выражение. Если получатель это истина, возвращается результат выполнения блока истины; иначе возвращается результат выполнения блока лжи.
истина: блок истина Условное выражение. Если получатель это истина, возвращается результат выполнения блока истины; иначе возвращается пусто.
ложь: блок ложь Условное выражение. Если получатель это ложь, возвращается результат выполнения блока лжи; иначе возвращается пусто.

Аргументы сообщений и: и или: должный быть блоками чтобы отложить вычисления. Условные выражения представлены как сообщения истина:ложь:, ложь:истина:, истина: и ложь:, как уже было указано и проиллюстрировано в предыдущих главах. Сообщения реализованы в подклассах Логики чтобы выполнился соответствующий блок.

В классе Истина, эти методы выглядят так:

истина: блок истина ложь: блок ложь
   блок истина значение.

ложь: блок ложь истина: блок истина
   блок истина значение.


истина: блок альтернатива
   блок альтернатива значение.


ложь: блок альтернатива
   пусто.

В классе Ложь, эти методы выглядят так:

истина: блок истина ложь: блок ложь
   блок ложь значение.

ложь: блок ложь истина: блок истина
   блок ложь значение.


истина: блок альтернатива
   пусто.


ложь: блок альтернатива
   блок альтернатива значение.

Если икс это 3, то

икс > 0 истина: [ иксикс - 1. ] ложь: [ иксикс + 1. ].

это интерпретируется так: икс > 0 вычисляется в истину, единственный экземпляра класса Истина; метод с селектором истина:ложь: находится в классе Истина, поэтому блок [ иксикс - 1. ] вычисляется без дальнейших проверок.

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

Дополнительный протокол класса ОбъектПравить

Протокол класса Объект, разделяемый всеми объектами, был введён в шестой главе. Несколько категорий сообщений не были включены в это начальное рассмотрение. Большинство сообщений из этой части протокола Объекта предоставляют поддержку системе для обработки сообщений, взаимоотношений зависимости, базовой обработки сообщений и примитивов системы.

Взаимоотношения зависимости между объектамиПравить

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

Классом Объект поддерживается дополнительный вид зависимости. Он предназначен для координации действий с различными объектами. В частности, его назначение заключается в возможности одним объектом, скажем А, ссылаться на другой объект, скажем Б, так чтобы Б был проинформирован об изменении произошедшем каким-либо образом в А. Информирование происходит об изменении А и о характере изменения, Б может решить произвести некоторые действия такие как обновление своего состояния. Поэтому концепция изменений и обновлений это составная часть поддержки этого третьего вида зависимости объектов.

Протокол класса Объект:

Протокол экземпляров Объекта
доступ к зависимостям
добавить зависимость: объект Добавляет аргумент, объект, в качестве одной из зависимостей получателя.
удалить зависимость: объект Удаляет аргумент, объект, из зависимостей получателя.
зависимости Возвращает Упорядоченный набор объектов которые зависят от получателя, то есть такие которые должны быть уведомлены при изменении получателя.
освободить Удаляет ссылки на объект которые могут ссылаться обратно на получателя. Это сообщение переопределяется любым подклассом который создаёт ссылки на зависимости; выражение супер освободить включается в каждое такое переопределение.
измемение и обновление
изменён Получатель изменён каким то способом; информирует все зависимости посылкой сообщения обновить:.
изменён: параметр Получатель изменён; изменение описывается параметром, параметр. Обычно аргумент это Символ являющийся частью протокола изменения зависимостей; в поведении по умолчанию используется получатель в качестве аргумента. Информируются все зависимости.
обновить: параметр Объект от которого зависит получатель был изменён. Получатель обновляет своё состояние (по умолчанию ничего не делается).

Рассмотрим в качестве примера объекты которые моделируют светофор. Обычный светофор это объект с тремя лампами, все разного цвета. Только один из них может быть включен в данный момент. В этом смысле включен или выключен огонь зависит от состояния других двух огней. Есть различные способы создать такую зависимость. Допустим мы создали класс Лампа как описано ниже.

имя класса Лампа
суперкласс Объект
имена переменных экземпляра состояние
методы класса
создание экземпляра
включенный
   сам новый включенный.

выключенный
   сам новый выключенный.

методы экземпляра
состояние
включить
   сам выключен истина: [ состояниеистина. сам изменён. ].

выключить
   сам включен истина: [ состояниеложь. ].

проверки
включен
   состояние.

выключен
   состояние не.

изменение и обновление
обновить: лампа
   лампа == сам ложь: [ сам выключить. ].
собственные
включенный
   состояниеистина.

выключенный
   состояниеложь.

Модель очень проста. Лампа либо включена либо выключена, поэтому флаг состояния хранится в переменной экземпляра; он равен истине если Лампа включена, либо лжи если Лампа выключена. Когда Лампа включается (включить), то она посылает себе сообщение изменён. Другие изменения состояния не рассылаются зависимостям т.к. предполагается что Лампа выключается в ответ на включение другой Лампы. По умолчанию в ответ на сообщение изменён всем зависимостям посылается сообщение обновить: сам (т.е. объект который был изменён это аргумент сообщения обновить:). Поэтому обновить: реализовано в Лампе так чтобы выключить её. Если параметр это получатель то, естественно, сообщение игнорируется.

Класс Светофор определён так чтобы можно было использовать любое количество связанных ламп. Сообщение создания экземпляра с: в качестве аргумента получает число Ламп. Каждая Лампа зависит от всех остальных Ламп. Когда Светофор разрушается, зависимости между его Лампами устраняются (сообщение наследуемое от класса Объект для устранения зависимостей это освободить; оно реализовано в Светофоре чтобы разослать сообщение всем Лампам).

имя класса Светофор
суперкласс Объект
имена переменных экземпляра лампы
методы класса
создание экземпляра
с: количество ламп
   сам новый ламп: количество ламп.
методы экземпляра
работа
включить: номер лампы
   (лампы от: номер лампы) включить.
инициализировать освободить
освободить
   супер освободить.
   лампы делать: [ :каждая лампа | каждая лампа освободить. ].
   лампыпусто.
собственные
ламп: количество ламп
   лампыРяд новый: (количество ламп макс: 1).
   лампы от: 1 пом: Лампа включенный.
   2
      до: количество ламп
      делать: [ :номер | лампы от: номер пом: Лампа выключенный. ].
   лампы
      делать: [
         :каждая лампа |
         лампы
            делать: [
               :зависимая лампа |
               каждая лампа ~~ зависимая лампа
                  истина: [ каждая лампа добавить зависимость: зависимая лампа. ]. ]. ].

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

   светофорСветофор с: 3.
   светофор включить: 2.
   светофор включить: 3.

Сообщение включить: посланное Светофору пересылает сообщение включить указанной Лампе. Если лампа в этот момент выключена, то она включается и посылается сообщение изменён. Сообщение изменён посылает сообщение обновить: каждой зависимости Лампы; если зависимая лампа включена, то она выключается.

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

Обработка сообщенийПравить

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

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

получатель выполнить: селектор.

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

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

Один из способов использования этого протокола это декодер команд пользователя. Допустим, например, что нужно смоделировать очень простой калькулятор в котором операнды предшествуют операторам. Возможная реализация представляет калькулятор у которого есть (1) текущий результат, который также является первым операндом, и (2) возможно неопределённый второй операнд. Каждый оператор это селектор сообщения понимаемого результатом. Посылка сообщения очистить, в первый раз, сбрасывает операнд; посылка сообщения очистить когда операнд сброшен сбрасывает результат.

имя класса Калькулятор
суперкласс Объект
имена переменных экземпляра результат операнд
методы класса
создание экземпляра
новый
   супер новый инициализировать.
методы экземпляра
доступ
результат
   результат.
вычисление
применить: оператор
   (сам отвечает на: оператор) ложь: [ сам ошибка: 'operation not understood'. ].
   операнд это пусто
      истина: [ результатрезультат выполнить: оператор. ]
      ложь: [ результатрезультат выполнить: оператор с: операнд. ].

очистить
   операнд это пусто истина: [ результат0. ] ложь: [ операндпусто. ].


операнд: число
   операндчисло.

собственные
инициализировать
   результат0.

Пример показывающий использование класса Калькулятор.

hpКалькулятор новый.

Создаёт hp как Калькулятор. Переменные экземпляра инициализируются: результат нулём, операнд пусто.

hp операнд: 3.

Представте что пользователь нажал кнопку с надписью 3 и задал операнд.

hp применить: #'+'.

Пользователь выбрал сложение. Метод применить: определят что оператор понимается и что операнд не пуст; поэтому результату присваивается значение выражения

результат выполнить: оператор с: операнд.

что эквивалентно

0 + 3

Метод присваивает результату 3; операнд остаётся равным 3 поэтому

hp применить: #'+'.

опять добавит 3, поэтому сейчас результат это 6.

   hp операнд: 1.
   hp применить: #'-'.
   hp очистить.
   hp применить: #в квадрате.

Результат был равен 6, вычли 1, и вычислили квадрат; сейчас результат равен 25.

Сообщения примитивы системыПравить

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

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

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

Следующий пример это метод расти из класса Словарь методов.

расти
   | новый сам ключ |
   новый самсам разновидность новый: сам основной размер.
   1
      до: сам основной размер
      делать: [
          |
         ключсам основной от: н.
         ключ не пусто: [ новый сам от: ключ пом: (ряд от: н). ]. ].
   сам становится: новый сам.

Обнаружено использование расширения AdBlock.


Викия — это свободный ресурс, который существует и развивается за счёт рекламы. Для блокирующих рекламу пользователей мы предоставляем модифицированную версию сайта.

Викия не будет доступна для последующих модификаций. Если вы желаете продолжать работать со страницей, то, пожалуйста, отключите расширение для блокировки рекламы.

Также на Фэндоме

Случайная вики