Как происходит отслеживание свободного экстента? |
Создание объектов и выполняемых систем
Почувствуй методологию: Принцип создания
Инвариант, эквивалентный True, является тривиальным. К тривиальным относится и любое свойство, предполагающее инициализацию полей значениями по умолчанию (ноль для числовых переменных, False — для булевских, Void — для ссылок).
Даже в случае отсутствия сильных инвариантов может быть полезно обеспечить в классе процедуры создания, позволяющие клиентам комбинировать создание с инициализацией полей. Класс POINT, описывающий точки на плоскости, может предоставить клиентам процедуры создания make_cartesian и make_polar, каждая с двумя аргументами, обозначающими координаты точки. Клиент может задать точку, указав либо декартовы координаты, либо — полярные координаты точки.
В некоторых случаях, POINT является тому примером, можно допускать обе формы создания пример 6.1 и пример 6.3. Этот случай описывается следующим образом:
class POINT create default_create, make_cartesian, make_polar feature … end
Здесь default_create — это имя метода (наследуемого всеми классами от общего предка) без аргументов, который по умолчанию помимо основной работы ничего больше не делает. Чтобы использовать эту процедуру, можно написать:
create your_point.default_create
Это можно выразить короче, в форме пример 6.1:
create your_point
Эта форма является корректной наряду с другими формами:
create your_point.make_cartesian (x, y) create your_point.make_polar (r, t)
Общее правило таково:
- если у класса нет предложения create, то это эквивалентно указанию одной из форм
create default_create
- перечисляющей default_create в качестве единственной процедуры создания;
- соответственно, оператор создания может быть записан в краткой форме
пример
6.1
create x без указания имени процедуры, либо в полной форме
create x.default_create
Так что концептуально можно полагать, что каждый класс имеет процедуру создания, необходимую для создания его экземпляров. Чтобы полностью построить build_a_line, нам осталось уточнить последнюю строку псевдокода: — "Create fancy_line". Это соответствует вызову еще одного оператора создания
create fancy_line.make_metro ("FANCY"
Здесь используется make_metro — одна из процедур создания класса LINE, которая создает линию метро, принимая в качестве аргумента имя этой линии, принадлежащее строковому типу.
Так как все это доступно как часть предопределенных примеров, то хорошая идея — пойти и прочесть окончательный текст.
Время чтения программы!
Рассмотрите текст build_a_line в классе LINE_BUILDING и убедитесь, что вы все прекрасно понимаете.
Как следствие предшествующего обсуждения, следует помнить, что необходимо создание объекта.
Создание экземпляра класса
- Если класс не имеет предложение create, используйте базисную форму, create x пример 6.1.
- Если класс имеет предложение create, перечисляющее одну или несколько процедур создания, используйте
пример
6.3
create x.make (...)
- где make - это одна из процедур создания, а в скобках указываются подходящие аргументы для make, если они присутствуют. Необходимо указать правильное число аргументов и их правильные типы. Необходимо также, чтобы аргументы удовлетворяли предусловию для make, если оно указано.
6.6. Корректность оператора создания
В соответствии с принципами Проектирования по Контракту для каждого изучаемого оператора мы должны точно знать:
- как корректно использовать оператор: его предусловие;
- что мы получим в результате выполнения оператора: его постусловие.
Помимо этого, классы (и циклы, как вскоре увидим) имеют инварианты, которые описывают свойства, сопровождающие выполнение операций.
Совместно свойства контракта определяют корректность любого программного механизма.
Приведем соответствующее правило для механизма создания.
Почувствуй методологию
Для корректности оператора создания перед его выполнением должно выполняться:
предусловие процедуры создания.
Следующие свойства должны иметь место после выполнения оператора создания, вызванного целью x типа С;
Если процедура создания не указана, то базисная форма create x тривиально удовлетворяет свойствам 1 и 3, поскольку не имеет ни предусловия, ни постусловия.
Предусловие процедуры создания (предложение 1) не требует, чтобы x имел значение void. Не является ошибкой последовательно создать два объекта с одной и той же целью x:
create x -После создания x не является void (смотри предложение 2) create x
Этот специфический пример полезен для понимания, хотя с содержательной точки зрения имеет изъян, поскольку объект, созданный первым оператором, будет немедленно забыт при выполнении второго оператора:
Второй оператор создания перенаправит ссылку на второй объект, так что первый объект станет бесполезным (вскоре мы поговорим подробнее о таких сиротливых объектах, не присоединенных ни к одной сущности).
Хотя два последовательных оператора создания в предыдущем примере не имеют смысла, варианты этой схемы могут быть полезными. Например, тогда, когда между операторами создания выполняются другие операторы, выполняющие полезные операции над первым объектом. Возможно, после создания первый объект будет куда-нибудь передан в качестве аргумента или записано его состояние.
Предложения со 2-го по 4-е определяют эффект выполнения оператора создания.
- Независимо от того, имела ли цель значение void, после вызова она это значение иметь не будет, поскольку результатом действия станет присоединение объекта (предложение 2).
- Если задана процедура создания, то ее постусловие будет иметь место для вновь созданного объекта (предложение 3).
- Помимо этого, объект будет удовлетворять инвариантам класса (предложение 4). Как установлено принципом инварианта, это требование является основой оператора создания: гарантируется, что объект, начинающий свою жизнь, удовлетворяет условиям согласованности, которые класс накладывает на все свои экземпляры.
Если инициализация по умолчанию не обеспечивает инвариант, то в обязанность процедуры создания входит корректировка ситуации таким образом, чтобы в итоге инвариант выполнялся.