Хорошо, смысл инварианта в том, что он описывает что-то, что верно для объекта во все времена . В этом случае что-то на гриле или нет (ничего между). Обычно они описывают свойство всего состояния объекта.
Предварительные и последующие условия описывают вещи, которые являются истинными непосредственно перед выполнением метода и сразу после него, и касаются только состояния, которое должно было быть затронуто методом . Это отличается, предположительно, от состояния объекта. Условия до и после могут рассматриваться как описание следа метода - только то, что ему нужно, то, что он коснулся.
Итак, на конкретный вопрос, идеи делают разные вещи, так что вы вполне можете хотеть и того, и другого. Вы, конечно, не можете просто использовать инварианты вместо предварительных и последующих условий - в этом случае частью инварианта объекта является «Что-то на гриле или нет», но предварительное условие lightOnFire должно знать, что элемент находится на гриле. Вы никогда не сможете вывести это из инварианта объекта. Это правда, что из предварительных и постусловий и известного начального состояния вы можете (предполагая, что структура объектов может изменяться только с помощью методов, а условия до и после описывают все изменения среды), вывести инвариант объекта. Тем не менее, это может быть сложным, и когда вы говорите вещи «на языке», проще просто предоставить и то, и другое.
Конечно, делать в вариантах, которые утверждают, что логический элемент является истинным или ложным, немного бессмысленно - система типов гарантирует это.