Инвариант класса - Википедия - Class invariant

В компьютерное программирование, конкретно объектно-ориентированного программирования, а инвариант класса (или же инвариант типа) является инвариантный используется для ограничения объекты из учебный класс. Методы класса должен сохранять инвариант. Инвариант класса ограничивает состояние, хранящееся в объекте.

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

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

Инварианты классов и наследование

Полезный эффект инвариантов классов в объектно-ориентированном ПО усиливается при наличии наследования. Инварианты класса наследуются, то есть «инварианты всех родителей класса применяются к самому классу».[1]

Наследование может позволить классам-потомкам изменять данные реализации родительских классов, поэтому класс-потомок может изменять состояние экземпляров таким образом, чтобы они были недействительными с точки зрения родительского класса. Обеспокоенность этим типом некорректного потомка - одна из причин, по которой разработчики объектно-ориентированного программного обеспечения предпочитают композиция выше наследования (т.е. наследование нарушает инкапсуляцию).[2]

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

Поддержка языков программирования

Утверждения

Общие языки программирования, такие как Python,[3] Поддержка JavaScript, C ++ и Java утверждения по умолчанию, который можно использовать для определения инвариантов класса. Обычный шаблон для реализации инвариантов в классах состоит в том, что конструктор класса генерирует исключение, если инвариант не выполняется. Поскольку методы сохраняют инварианты, они могут предполагать действительность инварианта и не должны явно проверять его.

Родная поддержка

Инвариант класса является важным компонентом дизайн по контракту. Итак, языки программирования, обеспечивающие полную нативная поддержка дизайна по контракту, Такие как Ржавчина, Эйфель, Ада, и D, также будет обеспечена полная поддержка инвариантов классов.

Неродная поддержка

За C ++, то Библиотека Локи предоставляет основу для проверки инвариантов классов, инвариантов статических данных и безопасности исключений.

Для Java есть более мощный инструмент под названием Язык моделирования Java это обеспечивает более надежный способ определения инвариантов классов.

Примеры

Родная поддержка

D

D язык программирования имеет встроенную поддержку инвариантов классов, а также других контрактное программирование Приведем пример из официальной документации.[4]

учебный класс Дата {  int день;  int час;  инвариантный() {    утверждать(день >= 1 && день <= 31);    утверждать(час >= 0 && час <= 23);  }}

Эйфель

В Эйфель, инвариант класса появляется в конце класса после ключевого слова инвариантный.

учебный класс	ДАТАСоздайте	делатьособенность {НИКТО} - Инициализация	делать (день: ЦЕЛОЕ; час: ЦЕЛОЕ)			- Инициализировать Current с помощью a_day и a_hour.		требовать			valid_day: день >= 1 и день <= 31			valid_hour: час >= 0 и час <= 23		делать			день := день			час := час		гарантировать			day_set: день = день			hour_set: час = час		конецособенность -- Доступ	день: ЦЕЛОЕ		- День месяца для Current	час: ЦЕЛОЕ		- Час дня для Currentособенность - Смена элемента	set_day (день: ЦЕЛОЕ)			- Установите для параметра day значение a_day		требовать			действительный_аргумент: день >= 1 и день <= 31		делать			день := день		гарантировать			day_set: день = день		конец	set_hour (час: ЦЕЛОЕ)			- Установите "час" на "a_hour"		требовать			действительный_аргумент: час >= 0 и час <= 23		делать			час := час		гарантировать			hour_set: час = час		конецинвариантный	valid_day: день >= 1 и день <= 31	valid_hour: час >= 0 и час <= 23конец

Неродная поддержка

C ++

В Локи (C ++) библиотека предоставляет фреймворк, написанный Ричард Спосато для проверки инвариантов классов, инвариантов статических данных и безопасность исключений уровень.

Это пример того, как класс может использовать Loki :: Checker для проверки того, что инварианты остаются верными после изменения объекта. В этом примере объект географической точки используется для хранения местоположения на Земле в виде координат широты и долготы.

Инварианты геоточек:

  • широта не может быть больше 90 ° северной широты.
  • широта не может быть меньше -90 ° южной широты.
  • долгота не может быть больше 180 ° восточной долготы.
  • долгота не может быть меньше -180 ° западной долготы.
#включают  // Требуется для проверки инвариантов класса.#включают <Degrees.hpp>учебный класс GeoPoint { общественный:  GeoPoint(Градусы широта, Градусы долгота);  /// Функция перемещения переместит местоположение GeoPoint.  пустота Двигаться(Градусы latitude_change, Градусы longitude_change) {    // Объект проверки вызывает IsValid при входе в функцию и выходе, чтобы доказать это    // Объект GeoPoint действителен. Проверка также гарантирует, что GeoPoint :: Move    // функция никогда не выбросит.    Проверить::CheckForNoThrow шашка(это, &Действует);    широта_ += latitude_change;    если (широта_ >= 90.0) широта_ = 90.0;    если (широта_ <= -90.0) широта_ = -90.0;    долгота_ += longitude_change;    пока (долгота_ >= 180.0) долгота_ -= 360.0;    пока (долгота_ <= -180.0) долгота_ += 360.0;  } частный:  / ** @note CheckFor выполняет проверку действительности во многих функциях, чтобы определить   если код нарушил какие-либо инварианты, если изменилось какое-либо содержимое или   функция вызвала исключение.   */  с помощью Проверить = ::Локи::Проверить<const GeoPoint>;  /// Эта функция проверяет все инварианты объекта.  bool Действует() const {    утверждать(это != nullptr);    утверждать(широта_ >= -90.0);    утверждать(широта_ <= 90.0);    утверждать(долгота_ >= -180.0);    утверждать(долгота_ <= 180.0);    возвращаться истинный;  }  Градусы широта_;   /// <Градусы от экватора. Положительный - север, отрицательный -                       /// <юг.  Градусы долгота_;  /// <Градусы от нулевого меридиана. Положительный - восток,                       /// <отрицательный - запад.}

Ява

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

общественный учебный класс Дата {    int / * @ spec_public @ * / день;    int / * @ spec_public @ * / час;    / * @ неизменный день> = 1 && день <= 31; @ * / // инвариант класса    / * @ инвариантный час> = 0 && час <= 23; @ * / // инвариант класса    /*@    @requires d> = 1 && d <= 31;    @requires h> = 0 && h <= 23;    @*/    общественный Дата(int d, int час) { // конструктор        день = d;        час = час;    }    /*@    @requires d> = 1 && d <= 31;    @ensures day == d;    @*/    общественный пустота setDay(int d) {        день = d;    }    /*@    @requires h> = 0 && h <= 23;    @ensures hour == h;    @*/    общественный пустота setHour(int час) {        час = час;    }}

Рекомендации

  1. ^ Мейер, Бертран. Построение объектно-ориентированного программного обеспечения, второе издание, Прентис Холл, 1997, стр. 570.
  2. ^ Э. Гамма, Р. Хелм, Р. Джонсон и Дж. Влиссидес. Паттерны проектирования: элементы объектно-ориентированного программного обеспечения многократного использования. Addison-Wesley, Reading, Massachusetts, 1995., стр. 20.
  3. ^ Официальные документы Python, утверждение утверждения
  4. ^ "Контрактное программирование - язык программирования D". dlang.org. Получено 2020-10-29.

внешняя ссылка