Concepts of Object-Oriented Programming AS 2017 Concepts of Object-Oriented Programming Midterm Examination 10.11.2017 Prof. Dr. Peter Müller Last name:................................. First name:................................. Student ID number:........................................................................ Department (if not D-INFK):............................................................... I confirm with my signature, that I was able to take this exam under regular circumstances and that I have read and understood the directions below. Signature:.................................................................................. Read completely and carefully the following instructions before starting to work on the exam: 1. Write your last and first name on every page that contains parts of your s. Use a ballpoint pen or a fountain pen (no pencil). Do not use a red pen. Return the instructions, the tasks, and your s. 2. It is neither allowed to use your own papers, documents, scripts, etc., nor any electronic equipment (notebook computers, calculators, cell phones, etc.) 3. Write all of your s in English. 4. Explain your s carefully if a task asks for an explanation. 5. You have 1 hour to complete the exam. SOLUTION 6. Place your student ID on the desk. Task 1 2 3 4 Total Max. points 7 14 8 8 37 Achieved Good Luck!
COOP Midterm Exam AS 2017 Name: 2/9 Task 1 Multiple Choice - 7 points In all of the following questions exactly one answer is correct. To get points, you need to mark only the correct answer. In all other cases you will get no points. A (4 points) Subtyping Consider the following types written in Java-like syntax: class D { A a; B foo(a a) throws RuntimeException; class F { C a; A foo(b a) throws RuntimeException; class G { A a; A foo(c a) throws Exception; class H { A a; A foo(a a) throws IndexOutOfBoundsException; Assume that B <: A, C <: A, and IndexOutOfBoundsException <: RuntimeException <: Exception. Which of the following subtype relations could be allowed by a sound type system? (a) D <: H and H <: G (b) D <: G and H <: F (c) CORRECT: D <: G and H <: G (d) H <: D and H <: F (e) None of the above Answer: a b c d e
COOP Midterm Exam AS 2017 Name: 3/9 B (3 points) Bytecode Verification Assume two Java classes A and B, and assume that B is a direct subclass of A. Consider the following Java bytecode: 0: iload 1 1: aload 2 2: astore 0 3: istore 2 4: aload 0 5: astore 2 6: goto 0 and assume that the input to instruction 0 is ([],[A,int,B]), where the first list indicates the content of the stack and the second list indicates the contents of the registers. The maximal stack size is equal to 2. Which of the following statements is true? (a) CORRECT: The type checker can successfully verify the code without needing type annotations for other instructions. (b) The bytecode cannot be verified due to a type mismatch at instruction 0. (c) The bytecode cannot be verified because in instruction 3 we are storing an integer in an object register. (d) The bytecode cannot be verified due to a stack underflow. (e) None of the above. Answer: a b c d e
COOP Midterm Exam AS 2017 Name: 4/9 Task 2 Behavioral Subtyping - 14 points A modifies clause is a part of a method specification that declares which heap locations can be modified by the method. As an example, in the following Java code, method foo is not allowed to write to any heap location besides this.x and other.x. class X { public int x; public int y; /// modifies (this.x, other.x) void foo(x other) {... A modifies clause can be interpreted as an implicit postcondition that states that all heap locations that are not listed will have the same value after the method invocation as before. A (7 points) A.1 When overriding a method, should it be allowed to expand the modifies clause, i.e., to include more modifiable heap locations? If yes, just write yes, otherwise provide a code example that demonstrates the problem when overriding method foo with an expanded modifies clause. No. class Y extends X { /// modifies (this.x, other.x, this.y) void foo(x other) { y = 2; public void client() { X x = new Y(); x.y = 12; x.foo(x); assert x.y == 12; A.2 When overriding a method, should it be allowed to reduce the modifies clause, i.e., to include less modifiable heap locations? If yes, just write yes, otherwise provide a code example that demonstrates the problem when overriding method foo with a reduced modifies clause. Yes. B (7 points) Consider the following Java code. class Y { public int n; public int k; /// requires i >= 0 /// modifies () /// ensures result >= k
COOP Midterm Exam AS 2017 Name: 5/9 public int m1(int i) {... /// requires n == k /// modifies (this.k) /// ensures result > old(k) public int m3() {... interface I { /// requires y.n > 0 /// modifies (y.n) /// ensures result > 0 public int m2(y y); class Z extends Y implements I { /// requires i > 0 (i < k && k <= 1) /// modifies () /// ensures result == old(k) + i public int m1(int i) {... /// requires y.n > 0 /// modifies (y.n) /// ensures result == y.n * y.n public int m2(y y) {... /// requires n >= k /// modifies (this.k) /// ensures result == n + 1 public int m3() {... Assume that there is no specification inheritance. B.1 Does method Z.m1 definitely fulfill all applicable requirements of behavioral subtyping? If yes, just write yes, otherwise point out the requirement that is violated. No. The precondition of Z.m1 is not compatible with the precondition of Y.m1. B.2 Does method Z.m2 definitely fulfill all applicable requirements of behavioral subtyping? If yes, just write yes, otherwise point out the requirement that is violated. No, it is not compatible with the postcondition of I.m2 (since y.n can be modified). B.3 Does method Z.m3 definitely fulfill all applicable requirements of behavioral subtyping? If yes, just write yes, otherwise point out the requirement that is violated. Yes (since this.n is not modified).
COOP Midterm Exam AS 2017 Name: 6/9 Task 3 Linearization - 8 points In this task you will have to model a traditional bakery, which produces and sells different types of Products. These Products satisfy the following subtype relations: Cake <: Dessert and BakedProduct <: Product BakedProduct <: Dessert ( <: means is NOT a subtype of ) Panettone <: BakedProduct and Panettone <: Cake A (3 points) An incomplete Scala implementation of the bakery is given below: class Product { override def tostring = "product" class Dessert { override def tostring = "dessert" class Cake { override def tostring = "cake" class BakedProduct { override def tostring = "baked " + super.tostring class Panettone { Fill in the boxes, such that the code above reflects at least the aforementioned subtype relations and it type checks. You are allowed to introduce new subtype relations in your, but you are NOT allowed to define new types. B (5 points) Now consider that the bakery offers two additional BakedProducts, modelled in Scala through the following traits: trait Bread extends BakedProduct { override def tostring = super.tostring + " or bread" trait SeasonalProduct extends BakedProduct { override def tostring = super.tostring + " for the holiday season" Fill in the empty lines from Task A by mixing-in the traits, such that for a client who orders a Panettone with SeasonalProduct with Bread (as shown below), cake or bread for the holiday season will be printed on the bill. // Client code: val panettone = new Panettone with SeasonalProduct with Bread println(panettone.tostring) // prints: cake or bread for the holiday season All the subtype relations from Task A must still hold. If one of the lines should remain empty, please explicitly write "/*none*/". The final code should type check.
COOP Midterm Exam AS 2017 Name: 7/9 Solution 1: class Product { override def tostring = "product" class Dessert extends BakedProduct /*none*/ { override def tostring = "dessert" class Cake extends Dessert /*none*/ { override def tostring = "cake" class BakedProduct extends Product /*none*/ { override def tostring = "baked " + super.tostring class Panettone extends Cake with Bread { Solution 2: class Product { override def tostring = "product" class Dessert extends BakedProduct /*none*/ { override def tostring = "dessert" class Cake extends Dessert /*none*/ { override def tostring = "cake" class BakedProduct extends Product /*none*/ { override def tostring = "baked " + super.tostring class Panettone extends Cake with Bread with SeasonalProduct {
COOP Midterm Exam AS 2017 Name: 8/9 Task 4 Overloading and Overriding - 8 points Consider the following class in Java: public class Person { protected double salary; public Person(double salary) { this.salary = salary; public boolean havesameincome(person other) { return this.salary == other.getincome(); public double getincome() { return salary; Consider also the following subclass of Person, a person with a spouse, which takes the salary of the spouse into account as well: public class MarriedPerson extends Person { private double spousesalary; public MarriedPerson(double salary, double spousesalary) { this.salary = salary; this.spousesalary = spousesalary; public boolean havesameincome(marriedperson other) { return this.getincome() == other.getincome(); public double getincome() { return ((salary + spousesalary) / 2); A (4 points) Show an example with variables p1,p2, such that p1.havesameincome(p2) returns false, but p1.getincome() == p2.getincome() returns true. In other words, fill in the following blank with valid code, such that the assertion below the following box is valid. Do not use reflection and assume that Person has no other subclasses. Person p1; MarriedPerson p2; p1 = new MarriedPerson(a,b); p2 = new MarriedPerson(c,d); for any a, b, c, d such that a + b = c + d but a (c + d)/2. assert (!p1.havesameincome(p2) && p1.getincome() == p2.getincome());
COOP Midterm Exam AS 2017 Name: 9/9 B (4 points) Propose changes to Person and MarriedPerson such that the assertion above will fail. B.1 Can you change only MarriedPerson.haveSameIncome, such that the assertion above will fail for your to subtask A? If yes, provide the modified method. Otherwise, explain why this is not possible. Yes, the following works. public boolean havesameincome(person other) { // changed MarriedPerson to Person in signature return this.getincome() == other.getincome(); B.2 Can you change only Person.haveSameIncome, such that the assertion above will fail for your to subtask A? If yes, provide the modified method. Otherwise, explain why this is not possible. Yes, the following works. public boolean havesameincome(person other) { return this.getincome() == other.getincome(); // changed calls to salary to getincome here Another trivial would be: public boolean havesameincome(person other) { return true; Also possible: Type-check with instanceof, then cast both to MarriedPerson and call havesameincome on casted objects. Also possible: Change parameter type to MarriedPerson.