Язык программирования D: контрактное программирование
Содержание:
1. Массивы и строки;
2. Семантика и шаблоны;
3. Функциональные типы и делегаты;
4. Модули и их тестирование;
5.Контрактное программирование (Вы читаете данный раздел).
В С++ структуры и классы - это практически одно и то же. В D2 они кардинально различаются. Структуры (struct) - это тип данных, инициализируемый статически и передаваемый по значению, не обладающий свойствами наследования и полиморфизма. Классы (class) - наоборот, всегда создаются оператором new и передаются только по ссылке. Классы наследуются и обладают полиморфизмом.
В D принципиально нельзя по ошибке создать класс статически, а потом долго мучиться из-за того, что не работают методы его базовых классов, как в С++.
Не нужно и явно работать с полиморфными указателями на класс - это делается неявно «под капотом». Нет и оператора «->» - он просто не нужен.
В последнее время контрактное программирование становится все более популярным способом увеличить надежность программ.
Его суть заключается в том, что на часть программы (класс, метод или функцию) накладывается ряд логических ограничений, называемых контрактами, которые должны быть истинными во время выполнения программы.
Код контрактов автоматически исключается из release-версии программы, поэтому важно понимать, что единственное назначение контрактов - проверка кода на «дуракоустойчивость» во время тестирования и отладки. В D2 есть несколько конструкций контрактного программирования. Самая простая - это директива assert, тело которой должно быть истинным выражением:
В отличие от С++ она встроена в язык и генерирует исключение AssertError при нарушении. Следующий тип контракта -пре- и пост-условия, обычно используемые для проверки аргументов и результата функции:
Блок in принудительно выполняется перед блоком body, а блок out - после него. «Магическая» переменная result получает значение, возвращаемое функцией. Последний тип контрактов - инварианты классов:
Код инварианта вызывается после конструктора, перед деструктором, а также перед и после каждого вызова функции, объявленной как public. В последней части статьи речь пойдет о стандартной библиотеке phobos и будут сделаны выводы о языке D.
1. Массивы и строки;
2. Семантика и шаблоны;
3. Функциональные типы и делегаты;
4. Модули и их тестирование;
5.
Структуры и классы
В С++ структуры и классы - это практически одно и то же. В D2 они кардинально различаются. Структуры (struct) - это тип данных, инициализируемый статически и передаваемый по значению, не обладающий свойствами наследования и полиморфизма. Классы (class) - наоборот, всегда создаются оператором new и передаются только по ссылке. Классы наследуются и обладают полиморфизмом.
В D принципиально нельзя по ошибке создать класс статически, а потом долго мучиться из-за того, что не работают методы его базовых классов, как в С++.
Не нужно и явно работать с полиморфными указателями на класс - это делается неявно «под капотом». Нет и оператора «->» - он просто не нужен.
Контрактное программирование
В последнее время контрактное программирование становится все более популярным способом увеличить надежность программ.
Его суть заключается в том, что на часть программы (класс, метод или функцию) накладывается ряд логических ограничений, называемых контрактами, которые должны быть истинными во время выполнения программы.
Код контрактов автоматически исключается из release-версии программы, поэтому важно понимать, что единственное назначение контрактов - проверка кода на «дуракоустойчивость» во время тестирования и отладки. В D2 есть несколько конструкций контрактного программирования. Самая простая - это директива assert, тело которой должно быть истинным выражением:
assert(expression);
В отличие от С++ она встроена в язык и генерирует исключение AssertError при нарушении. Следующий тип контракта -пре- и пост-условия, обычно используемые для проверки аргументов и результата функции:
long square_root(long x) in {
assert(x >= 0);
}
out (result) {
assert((result * result) = x);
}
body {
return cast(long)std.math.sqrt(cast(real)x);
}
assert(x >= 0);
}
out (result) {
assert((result * result) = x);
}
body {
return cast(long)std.math.sqrt(cast(real)x);
}
Блок in принудительно выполняется перед блоком body, а блок out - после него. «Магическая» переменная result получает значение, возвращаемое функцией. Последний тип контрактов - инварианты классов:
class Date { int day; int hour;
invariant() {
assert(1 <= day ss day <= 31); assert(0 <= hour ss hour < 24);
}
}
invariant() {
assert(1 <= day ss day <= 31); assert(0 <= hour ss hour < 24);
}
}
Код инварианта вызывается после конструктора, перед деструктором, а также перед и после каждого вызова функции, объявленной как public. В последней части статьи речь пойдет о стандартной библиотеке phobos и будут сделаны выводы о языке D.