Download presentation
Presentation is loading. Please wait.
Published byLogan Cole Modified over 6 years ago
1
The following slides contain advanced material and are optional.
2
Outline Invariants Violating the invariant Marriage problem
3
Invariants explained in 60 seconds
Consistency requirements for a class Established after object creation Hold, when an object is visible Entry of a routine Exit of a routine class ACCOUNT feature balance: INTEGER invariant balance >= 0 end
4
Temporary violation Invariants can be violated temporarily
e.g. on object creation In Eiffel, invariants are checked on entry and exit of a qualified feature call One exception: for calls to creation procedures, invariants are not checked on entry to routine e.g create cell.set_item (1) But checked for normal call: cell.set_item (1) See demo. Open project „invariant“, open class A, comment out one line at a time. First ask students what will happen, then run it.
5
Public interface of person (without contracts)
class PERSON feature spouse: PERSON -- Spouse of Current. marry (a_other: PERSON) -- Marry `a_other’. do … end class MARRIAGE feature make local alice: PERSON bob: PERSON do create alice create bob bob.marry (alice) end
6
Hands-On Write the contracts
class PERSON feature spouse: PERSON marry (a_other: PERSON) require ?? ensure invariant end Open „person_empty_interface.e“ in external editor and fill in all contracts and body of „make“
7
A possible solution class PERSON feature spouse: PERSON marry (a_other: PERSON) require a_other /= Void a_other /= Current a_other.spouse = Void spouse = Void ensure spouse = a_other a_other.spouse = Current end invariant spouse /= Void implies spouse.spouse = Current spouse /= Current If boolexpr1 and boolexpr2 are boolean expressions, and boolexpr1 evaluates to false, is boolexpr1 implies boolexpr2 always true? Yes, because boolexpr1 implies boolexpr2 is equivalent to not boolexpr1 or else boolexpr2
8
Implementing marry class PERSON feature spouse: PERSON marry (a_other: PERSON) require a_other /= Void a_other /= Current a_other.spouse = Void spouse = Void do ?? ensure spouse = a_other a_other.spouse = Current end invariant spouse /= Void implies spouse.spouse = Current spouse /= Current
9
No assigner command for a_other
Implementing marry I Hands-On class PERSON feature spouse: PERSON marry (a_other: PERSON) require a_other /= Void a_other /= Current a_other.spouse = Void spouse = Void do a_other.spouse := Current spouse := a_other ensure spouse = a_other a_other.spouse = Current end invariant spouse /= Void implies spouse.spouse = Current spouse /= Current Compiler Error: No assigner command for a_other
10
Hands-On Implementing marry II bob, alice: PERSON
class PERSON feature spouse: PERSON marry (a_other: PERSON) require a_other /= Void and a_other /= Current a_other.spouse = Void spouse = Void do a_other.set_spouse (Current) spouse := a_other ensure spouse = a_other a_other.spouse = Current end set_spouse (a_person: PERSON) spouse := a_person invariant spouse /= Void implies spouse.spouse = Current spouse /= Current local bob, alice: PERSON do create bob; create alice bob.marry (alice) bob.set_spouse (Void) -- What about the invariants -- of bob and alice? end After “set_spouse (Void)”, invariant of bob is Ok, but the invariant of alice is violated
11
Implementing marry III
Hands-On class PERSON feature spouse: PERSON marry (a_other: PERSON) require a_other /= Void and a_other /= Current a_other.spouse = Void spouse = Void do a_other.set_spouse (Current) spouse := a_other ensure spouse = a_other a_other.spouse = Current end feature {PERSON} set_spouse (a_person: PERSON) spouse := a_person invariant spouse /= Void implies spouse.spouse = Current spouse /= Current What about the invariant of a_other in feature marry? Invariant of a_other is violated after call to set_spouse set_spouse (a_person: PERSON) -- Set `spouse' to `a_person'. require person_not_current: a_person /= Current do spouse := a_person ensure spouse_set: spouse = a_person end It is ok that a_person can be void. This is needed to the divorce feature
12
Implementing marry : final version
class PERSON feature spouse: PERSON marry (a_other: PERSON) require a_other /= Void a_other.spouse = Void spouse = Void do spouse := a_other a_other.set_spouse (Current) ensure spouse = a_other a_other.spouse = Current end feature {PERSON} set_spouse (a_person: PERSON) spouse := a_person invariant spouse /= Void implies spouse.spouse = Current spouse /= Current Reverting the instructions does the trick because the invariant of Current is checked at the end of feature marry
13
Is the order of instructions in divorce important for the invariant?
Ending the marriage Hands-On class PERSON feature spouse: PERSON divorce require spouse /= Void do spouse.set_spouse (Void) spouse := Void ensure spouse = Void (old spouse).spouse = Void end invariant spouse /= Void implies spouse.spouse = Current spouse /= Current Is the order of instructions in divorce important for the invariant?
14
What we have seen Invariant should only depend on Current object
If invariant depends on other objects Take care who can change state Take care in which order you change state Invariant can be temporarily violated You can still call features on Current object Take care in calling other objects, they might call back Although writing invariants is not that easy, they are necessary to do formal proofs. This is also the case for loop invariants (which will come later).
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.