Written on
GContracts: Inheritance of Pre- and Postconditions
GContracts 1.1.0 [0] introduced inheritance for pre- and postconditions and optimized class invariant inheritance. If you want to know more about GContracts take a look at the wiki [1] or at blog-posts tagged with "gcontracts".What about postcondition inheritance?
Postconditions are used to specify what work is guaranteed by the supplier to be done in a specific method, under the condition that the precondition is satisfied. When inheritance comes into play, postconditions of a parent class are inherited by overridden methods of a descendant class. Imagine a class Stack which provides methods for modifying objects kept in LIFO order.import org.gcontracts.annotations.*
@Invariant({ elements != null })
class Stack {
private List elements
@Ensures({ is_empty() })
public Stack() {
elements = []
}
@Requires({ preElements?.size() > 0 })
@Ensures({ !is_empty() })
public Stack(List preElements) {
elements = preElements
}
def boolean is_empty() {
elements.isEmpty()
}
@Requires({ !is_empty() })
def last_item() {
elements.last()
}
def count() {
elements.size()
}
@Ensures({ result == true ? count() > 0 : count() >= 0 })
def boolean has(def item) {
elements.contains(item)
}
@Ensures({ last_item() == item })
def put(def item) {
elements.push(item)
}
@Requires({ !is_empty() })
@Ensures({ last_item() == item })
def replace(def item) {
remove()
elements.push(item)
}
@Requires({ !is_empty() })
@Ensures({ result != null })
def remove() {
elements.pop()
}
def String toString() { elements.toString() }
}
def stack = new Stack()
stack.push(['value1', 'value2', 'value3'])
class GroovyStack extends Stack {
@Override
def put(def item) {
if (item instanceof List) item.each { super.put(it) }
else super.put(item)
return item
}
}
[inherited postcondition] in method <put(item:java.lang.Object)> violated. Expression: (this.last_item() == item). Values: item = [1, 2, 3, 4]
class GroovyStack extends Stack {
@Override
@Ensures({ item instanceof List ? item.last() == last_item() : item == last_item() })
def put(def item) {
if (item instanceof List) item.each { super.put(it) }
else super.put(item)
return item
}
}
[inherited postcondition] in method <put(item:java.lang.Object)> violated. Expression: (this.last_item() == item). Values: item = [1, 2, 3, 4]

Stack stack = StackFactory.getInstance()
stack.put([1,2,3,4])
What about precondition inheritance?
Preconditions are used to specify certain conditions which must be fulfilled by a client so that a method call on an object succeeds. So far, GContracts did not support inheritance of preconditions, meaning that whenever a parent class defined a precondition on a method which has been overridden in a descendant, the precondition in the descendant had to be newly defined. In contrast with postconditions, preconditions weaken the parent's preconditions. Whenever a parent class defines a precondition on a method, an overridden method might define additional preconditions which might be fulfilled by a client, but don't have to be.
@Requires({ item != null })
@Ensures({ item() == item })
def replace(def item) {
super.replace(item)
}