Skip to content

Commit 360eaf0

Browse files
committed
Better
1 parent 8d16fca commit 360eaf0

4 files changed

Lines changed: 19 additions & 11 deletions

File tree

tutorial/exercises/Animal2.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,6 @@ public Animal2(String g)
1919

2020
public void setAge(int a) {
2121
if (a < _age) { return; }
22-
if (_age <= a && a <= 150) { _age = a; }
22+
_age = a;
2323
}
2424
}

tutorial/exercises/ExceptionalSetAge2.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,6 @@ public interface ExceptionalSetAge2 extends Age {
33
/*@ normal_behavior
44
@ requires a < age;
55
@ assignable \nothing;
6-
@ ensures \old(age) == age; @*/
6+
@*/
77
void setAge(int a);
88
}

tutorial/exercises/InheritingSpecificationsEx.md

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -74,14 +74,13 @@ c. **If the inherited implementations of the methods `setX` and `setY` are not c
7474
```
7575

7676
## **Question 3**
77-
**Specify another interface, called `ExceptionalSetAge`, that also includes a new method `setAge` (new compared to `Age`, that is). The interface `ExceptionalSetAge` must extend the interface `Age` shown above. The added `setAge` method should take an integer that is (strictly) less than the value of `age` and throw an `IllegalArgumentException`. When this happens, the method should not assign to any variables.
78-
However, so that further exercises may involve classes that extend both `NormalSetAge` and this interface (`ExceptionalSetAge`) and which can assign to additional fields, it is necessary to allow the inherited model field `age` to be assigned by the `setAge` method. So think about what postcondition would specify the appropriate behavior.**
77+
**Specify another interface, called `ExceptionalSetAge`, that also includes a new method `setAge` (new compared to `Age`, that is). The interface `ExceptionalSetAge` must extend the interface `Age` shown above. The added `setAge` method should take an integer that is (strictly) less than the value of `age` and throw an `IllegalArgumentException`. When this happens, the method should not assign to any variables.**
7978

8079
## **Question 4**
81-
**Specify an interface, called `Gendered` that includes a model instance field `gender` of type `String`. Your task is to write this interface's specification and to specify a Boolean-valued `spec_pure` method named `isFemale()` that returns `true` just when the receiver (an object of a subtype of `Gendered`) is has the gender female.**
80+
**Specify an interface, called `Gendered` that includes a model instance field `gender` of type `String`. Your task is to write this interface's specification and to specify a Boolean-valued `spec_pure` method named `isFemale()` that returns `true` just when the receiver (an object of a subtype of `Gendered`) is has the gender value `"female"`.**
8281

8382
## **Question 5**
84-
**Specify and correctly implement a class, call it `Animal` that implements the interfaces `Gendered`, `NormalSetAge`, and `ExceptionalSetAge`. You will need to implement a constructor that takes a `String` argument that determines the gender of the new object, but starts the age at 0. You may assume that animals are either male or female. Hints: think about the precondition of the constructor. Use a protected field `_gen` to represent the model field `gender` that is inherited from the (specification of the) interface `Gendered`. Note that each model field names a datagroup, and when a concrete field is used to represent that datagroup, then it must be added into that datagroup using an `in` annotation in JML. Being in a datagroup allows the representing field to be assigned when the datagroup is allowed to be assigned by the specification. Similarly, add a protected model field `_age` that is used to represent the inherited model field `age`. Making these concrete fields protected allows them to be inherited by subclasses of Animal. Since they are protected, the represents clauses that are used must also be protected. [See the lesson on model fields and datagroups](https://www.openjml.org/tutorial/ModelFields) for more about represents clauses.**
83+
**Specify and correctly implement a class, call it `Animal` that implements all three interfaces `Gendered`, `NormalSetAge`, and `ExceptionalSetAge`. You will need to implement a constructor that takes a `String` argument that determines the gender of the new object, but starts the age at 0. You may assume that animals are either male or female. Hints: think about the precondition of the constructor. Use a protected field `_gen` to represent the model field `gender` that is inherited from the (specification of the) interface `Gendered`. Note that each model field names a datagroup, and when a concrete field is used to represent that datagroup, then it must be added into that datagroup using an `in` annotation in JML. Being in a datagroup allows the representing field to be assigned when the datagroup is allowed to be assigned by the specification case's frame condition. Similarly, use a protected model field `_age` to represent the inherited model field `age`. Making these concrete fields protected allows them to be inherited by subclasses of `Animal`. Since they are protected, the represents clauses that are used must also be protected. [See the lesson on model fields and datagroups](https://www.openjml.org/tutorial/ModelFields) for more about represents clauses.**
8584

8685
## **Question 6**
8786
**Specify and implement a class `Human` as a subclass of `Animal`. A `Human` should have a Boolean-valued public model field `discount` that is represented by some protected concrete (instance) field. The `setAge` method should have an additional specification case that makes `discount` be `true` when the age used as an argument to `setAge` is 65 or greater. Hint: use a call to `super` in your implementation of `setAge`.**
@@ -92,8 +91,11 @@ However, so that further exercises may involve classes that extend both `NormalS
9291
## **Question 8**
9392
**Specify an `equals` method for the interface `Gendered`. Then correctly implement it in the class `Animal`. Make sure that two Animals (or Humans or Tortoises) with different ages are not equal, even if they have the same gender.**
9493

94+
## Advanced Exercises
95+
The following two exercises delve into deeper aspects of specification inheritance and can be skipped on first reading.
96+
9597
## **Question 9**
96-
**Specify a version of the interface `ExceptionalSetAge`, call it `ExceptionalSetAge2` that instead of throwing an exception when the arugment is strictly less than `age`, the `setAge` method should not assign to anything.**
98+
**Specify a version of the interface `ExceptionalSetAge`, call it `ExceptionalSetAge2` that instead of throwing an exception when the argument is strictly less than `age`, the `setAge` method should have a normal behavior that returns without assigning anything.**
9799

98100
## **Question 10**
99101
**Specify and correctly implement versions of the classes `Animal` and `Human` that inherit from `ExceptionalSetAge2`.

tutorial/exercises/InheritingSpecificationsExKey.md

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ This exercise shows that preconditions can be further weakened in a subtype, as
150150
Note that the method setAge cannot simply be inherited, because the precondition of the method `setAge` in the class `Animal` has a different precondition, and that precondition must be weakened in the implementation in `Tortoise`.
151151

152152
## **Question 8**
153-
One way to specify an interface like `Gendered` but with an `equals` method that allows for other attributes (aside from the gender) to be taken into account is to say that when the genders are differnt, then the `equals` method must return false. This has the advantage of allowing other attributes of an object to be considered, while requiring comparison of the genders. This is shown in the following.
153+
One way to specify an interface like `Gendered` but with an `equals` method that allows for other attributes (aside from the gender) to be taken into account is to say that when the genders are different, then the `equals` method must return false. This has the advantage of allowing other attributes of an object to be considered, while requiring comparison of the genders. This is shown in the following.
154154

155155
```
156156
public interface GenderedWithEquals {
@@ -174,6 +174,8 @@ However, this cannot be strengthened to say that when the genders are equal, the
174174

175175
Also recall that Java's `instanceof` operator returns false if its left-hand argument is null. Thus, when `obj instanceof GenderedWithEquals` is true, we know that `obj` must not be null, and so a cast will work.
176176

177+
## Advanced Exercises
178+
177179
## **Question 9**
178180
One solution is the following.
179181

@@ -182,13 +184,15 @@ public interface ExceptionalSetAge2 extends Age {
182184
/*@ normal_behavior
183185
@ requires a < age;
184186
@ assignable \nothing;
185-
@ ensures \old(age) == age; @*/
187+
@*/
186188
void setAge(int a);
187189
}
188190
```
189191

192+
Sine this behavior specification is in an interface, it has public visibility and thus does not need to be use the modifier `public`. It would be possible to specify a postcondition (for example `age == \old(age)` would work), but the default of `true` suffices in this case, because of the specified frame. However, one should not specify the method as `pure`, because `pure` applies to the entire method and not just one specification case.
193+
190194
## **Question 10**
191-
A class that is similar to `Animal`, called `Animal2` below, inherits from the aabove interface `ExceptionalSetAge2`. Notice that in the implementation of `setAge` obeys both specifications of the method `setAge`.
195+
A class that is similar to `Animal`, called `Animal2` below, inherits from the above interface `ExceptionalSetAge2`. Notice that in the implementation of `setAge` obeys both specifications of the method `setAge`.
192196

193197
```
194198
public class Animal2 implements Gendered,
@@ -211,7 +215,7 @@ public class Animal2 implements Gendered,
211215
212216
public void setAge(int a) {
213217
if (a < _age) { return; }
214-
if (_age <= a && a <= 150) { _age = a; }
218+
_age = a;
215219
}
216220
}
217221
@@ -240,3 +244,5 @@ public class Human2 extends Animal2 {
240244
}
241245
}
242246
```
247+
248+
Notice that the implementation of `setAge` in `Human2` cannot just make a super call, as such a call `super.setAge(a)` would simply return to the code of `setAge` in `Human2`, whereas in the class `Human` that call would throw an exception. It is thus necessary to prevent an assignment to `_discount` (which is in the datagroup `age`) by returning when the argument `a` is strictly less than `_age`.

0 commit comments

Comments
 (0)