Docsity
Docsity

Prepare for your exams
Prepare for your exams

Study with the several resources on Docsity


Earn points to download
Earn points to download

Earn points by helping other students or get them with a premium plan


Guidelines and tips
Guidelines and tips

Subtyping and Behavioral Subtyping: Identifying Subclasses that Preserve Contracts, Exercises of Java Programming

Data Structures and AlgorithmsSoftware EngineeringJava ProgrammingObject-Oriented Programming

The concept of subtyping and behavioral subtyping in Java, focusing on the X class and its method foo. which of the classes A, B, C, and D can be substituted for ZZZ without violating the contracts of the X class. Additionally, the document covers inheritance, dynamic method binding, multiple inheritance, and linearization, as well as bytecode verification and parametric polymorphism.

What you will learn

  • Which class can be substituted for ZZZ in the X class such that no contracts will be violated?
  • What is the difference between subtyping and behavioral subtyping?
  • How does parametric polymorphism work in Java?
  • What is the role of bytecode verification in Java?
  • How does inheritance affect subtyping in Java?

Typology: Exercises

2021/2022

Uploaded on 02/11/2022

alpa
alpa 🇺🇸

4.4

(19)

8 documents

1 / 12

Toggle sidebar

Related documents


Partial preview of the text

Download Subtyping and Behavioral Subtyping: Identifying Subclasses that Preserve Contracts and more Exercises Java Programming in PDF only on Docsity! Concepts of Object-Oriented Programming AS 2018 Exercise 13 Self-Study Exercise Sheet NOTE: This exercise sheet will not be discussed in an exercise session. We publish it now together with the solution to allow you to better prepare for the final exam. If you have any questions regarding this sheet, please consult your assistant. Subtyping and Behavioral Subtyping Task 1 Consider the class X and its only method foo where ZZZ is placeholder for a class name: class X { /// requires x>0 ∧ (¬∃ i,j: int | 2 ≤ i,j ≤ x ∧ i*j=x) /// ensures result>0 ∧ result % 2 = 0 int foo(final int x){ return (new ZZZ()).foo(x); } } Which of the four classes below could be substituted for ZZZ such that no contracts will be violated? (a) class A { /// requires x≥0 /// ensures result = x+1 int foo(final int x) {...} } (b) class B { /// requires true /// ensures result%2 = 0 int foo(final int x) {...} } (c) class C { /// requires x%2 = 1 /// ensures result = x+1 int foo(final int x) {...} } (d) class D { /// requires true /// ensures result = x*(x+1) int foo(final int x) {...} } Inheritance, Dynamic Method Binding, Multiple Inheritance, and Linearization Task 2 Consider the following Java classes and interfaces: public interface IA { IA g(IA x); } public interface IB extends IA { IB g(IA x); IA g(IB x); } public interface IC extends IA { IC g(IB x); } class B implements IB { public IB g(IA x){System.out.print("B1");return null;} public IC g(IB x){System.out.print("B2");return null;} } class C implements IC { public IC g(IA x){System.out.print("C1");return null;} public C g(IB x){System.out.print("C2");return null;} } class Main{ public static void main(String[] args) { B b = new B(); C c = new C(); IA a1 = b; IA a2 = c; IA r1 = a1.g(a2); IA r2 = a2.g(b); IC r3 = b.g(b); IA r4 = c.g(a2); C r5 = c.g(b); } } What is the output of the execution of the Main.main method? Explain your answer. class Zoo{ void feedAnimal(Cage cage){ /*code given in each section*/ } <F extends Food>void feed(F food, Animal<F> animal){animal.eat(food);} void manage(){ /*your code here*/ } } Clearly a Wolf can eat a Sheep but not the other way around. In the following subtasks we explore if relaxing some of the Java type rules can lead to a situation where a Sheep can eat a Wolf - that is, the method eat is called on an object of the dynamic type Sheep with an argument object of the dynamic type Wolf. All the code you give in the answers to the following sections is in the same package as the code above, and must type check in standard Java. The top method that is called in all sections is Zoo.manage. You can assume that method call arguments are evaluated left to right, and that the program is sequential. You are not allowed to use reflection, raw types, or type-casts. A) Assume the following body of Zoo.feedAnimal(Cage cage), which is rejected by the Java type checker: { feed(cage.getAnimal().lunchBag,cage.getAnimal()); } Make a Sheep eat a Wolf assuming the body of feedAnimal is exempted from the type checker. Show all necessary code. You are only allowed to change the Cage class and provide the body of the Zoo.manage method. B) Assume the following body of Zoo.feedAnimal(Cage cage), which is rejected by the Java type checker: {feed(cage.animal.getLunchBag(),cage.animal);} Can you make a Sheep eat a Wolf if the body of feedAnimal is exempted from the type checker? If so, show all necessary code, otherwise explain why not. You are only allowed to change the Cage class, provide the body of the Zoo.manage method, and add new classes. C) Answer the question in the previous section, assuming the field Cage.animal is final. Explain your answer. Reminder: Java’s final fields can be assigned to only in the constructor of the class that declares them. D) Assume the following body of Zoo.feedAnimal(Cage cage), which is rejected by the Java type-checker: {feed(cage.animal.lunchBag,cage.animal);} Can you make a Sheep eat a Wolf if the body of feedAnimal is exempted from the type- checker? If so, show all necessary code, otherwise explain why not. E) Which of the above cases, that is safe in the sequential case, is unsafe in a multithreaded program? For each such case, explain what can happen in the multithreaded case that cannot in the sequential case. F) The current Java rule for evaluating an expression (including a method call) with wildcard typed arguments is to capture each wildcard in the arguments separately. Propose a more lenient wildcard capture rule than current Java, that is typesafe and accept all the above cases that you deem safe. Hint: define "stable" paths that cannot be modified by calls. Information Hiding and Encapsulation Task 6 Suppose that we have a language with the information hiding rules of Java, but with structural subtyping. What should be the subtyping relations between the following three classes? class A {int foo();} class B {protected int foo();} class C {public int foo();} Task 7 Consider the class Hour, defined as follows: public class Hour { protected int h=0; /// invariant h>=0 && h<24 public void set(int h) { if(h>=0 && h<24) this.h=h; } } What is the external interface of Hour? Can we extend the code, without changing the class, so that the invariant is broken? If yes, provide an example, and propose how to fix the class. Task 8 Information Hiding Consider the following Java program consisting of two packages BTC and B2X: 1 package BTC; 2 3 public class Chain { 4 5 /// ensures result <= 2 6 _______ int max_size() { 7 return 2; 8 } 9 } 10 11 package B2X; 12 import BTC.*; 13 14 public class Chain2x extends Chain { 15 16 /// ensures result <= 4 17 protected int max_size() { 18 return 4; 19 } 20 } A)What is themost permissive access modifier for the method max_size() in class Chain such that class Chain2x is a behavioral subtype of Chain? Assume that we do not use specification inheritance. Fill the blank above with your answer. Explicitly write default for a default access modifier. Write none if no choice of access modifier allows Chain2x to be a behavioral subtype of Chain. B) We now add a class Block and a subclass Block2x to package BTC: 1 package BTC; 2 3 public class Block { 4 5 protected int num; 6 /// invariant: 1 <= num 7 8 public Block(int n) { 9 num = (n < 1 ? 1 : n); 10 } 11 12 } 13 14 public class Block2x extends Block { 15 16 /// invariant: 2 <= num 17 protected Block pred; 18 /// invariant: pred != null ==> pred.num < num 19 20 public Block2x(int n, Block b) { 21 super(n < 1 ? 2 : 2*n); 22 pred = (b != null && 2 <= b.num && b.num < num ? b : null); 23 } 24 25 } B.1 Do the invariants in Block and Block2x satisfy the requirements of behavioral subtyping? Assume that we do not use specification inheritance. Briefly explain your answer. B.2 A class C is correct with respect to its invariants if all constructors of C establish the invariants of the new object and all exported methods m of C preserve the invariants of the receiver object, that is, the invariant holds in the poststate of m provided that it held in the prestate of m. Are classes Block and Block2x correct with respect to their invariants? Briefly explain your answer. C) We now want to extend the code in part B with methods that preserve the invariants of the class in which they are declared but that make it possible to violate the invariants of Block2x from client code in another package. C.1 Extend the code in part B with a method that preserves the invariants of the class in which it is declared but makes it possible to violate the first invariant of class Block2x (i.e., 2 <= num) from client code in package B2X. Specify in which class you want to declare the method, write the method, and write the client code that violates the invariant. C.2 How can you prevent the code that you wrote in part C.1 from violating the invariant by further extending the code in part B? You are not allowed to modify existing code. Write the code that fixes the specific problem you exploited in part C.1. C.3 Extend the code in part B with a method that preserves the invariants of the class in which it is declared but makes it possible to violate the second invariant of class Block2x (i.e., pred != null ==> pred.num < num) from client code in package B2X in a way that cannot be prevented by further extending the code in part B. Specify in which class you want to declare the method, write the method, and write the client code that violates the invariant. public Number x; // Remark: Number is a super-interface for public Number y; // Integer, Double, etc. public Vector (Number x, Number y) { this.x = x; this.y = y; } } Suppose that in some other class we write the following method to calculate the length of the vector represented by a Vector object: public double vectorLength(Vector c) { double x = c.x.doubleValue(); double y = c.y.doubleValue(); return Math.sqrt(x * x + y * y); } A) This implementation is unsafe - when executed it may throw exceptions. Why? Is this a reasonable behavior? B) Add a pre-condition for the method, specifying what is required to be safe. C) Suppose you are allowed to modify the signature of the method to include non-null type annotations. To what extent can you weaken the necessary pre-condition? D) Suppose that you are also allowed to upgrade the class Vector to include reasonable non- null type annotations. How does this affect your previous answer? Do these changes to the class seem reasonable? Task 13 Consider the following three classes (declared in the same package): public class Person { Dog? dog; // people might have a dog public Person() { } } public class Dog { Person! owner; // Dogs must have an owner Bone! bone; // Dogs must have a bone String! breed; // Dogs must have a breed public Dog(Person owner, String breed) { this.owner = owner; this.bone = new Bone(this); this.breed = breed; } } public class Bone { Dog! dog; // Bones must belong to a dog.. public Bone(Dog toOwn) { this.dog = toOwn; } } A)Annotate the code with non-null and construction type annotations where they are necessary. Explain why the code now type-checks according to construction types. B) Could we provide constructors for classes Dog and Bone with no parameters? C) Now, suppose a (possibly mad) scientist wants to extend the implementations of these classes with some genetic engineering. Firstly, we want to be able to “clone” a bone. We can add the following method to class Bone to make a copy of an existing bone, and assign it to another Dog: public Bone clone(Dog toOwn) { return new Bone(toOwn); } However, our scientist would like to go further, and be able to clone dogs. A cloned Dog should also have its bone cloned along with it, but may be assigned to a new owner: we add the following extra constructor and method to class Dog: Dog(Dog toClone, Person newOwner) { this.owner = newOwner; this.breed = toClone.breed; this.bone = new Bone(this); } public Dog clone(Person toOwn) { return new Dog(this, toOwn); } However, our scientist would like to go still further, and be able to clone people. A cloned Person should also have its dog (if any) cloned along with it: we add the following extra constructor and method to class Person: Person(Person toClone) { Dog? d = toClone.dog; if(d!=null) { this.dog = new Dog(d, this); } } public Person clone() { return new Person(this); } Annotate this extra code with appropriate non-null and construction types annotations. You should guarantee that each of the clone methods (which belong to the public interface) return a committed reference. You should ensure that your answers guarantee that all of the code type-checks - explain your choices. Hint: think carefully about how constructor calls are typed, and what happens if the construc- tors are called in more than one situation. Reflection Task 14 Which of the following is the defining characteristic of reflection? (a) It allows for much simpler code (b) It enables more flexibility (c) It allows a program to observe and modify its own structure and behavior (d) It is not statically safe (e) It may hurt performance (f) None of the above Task 15 Consider the following Java code: void foo() throws java.lang.Exception { LinkedList<String> xs = new LinkedList<String>(); xs.add("A"); xs.add("B"); xs.add("C"); Class<?> c = xs.getClass(); Method remove = c.getMethod("remove"); xs.add(remove.invoke(xs)); } which uses the following methods of class LinkedList<E> public E remove() public boolean add(E e) Which of the following statements is true? The invocation of . . . (a) c.getMethod("remove") is rejected by the compiler (b) c.getMethod("remove") raises an exception (at run time) (c) remove.invoke(xs) is rejected by the compiler (d) remove.invoke(xs) raises an exception (at run time) (e) xs.add(...) is rejected by the compiler (f) xs.add(...) raises an exception (at run time)
Docsity logo



Copyright © 2024 Ladybird Srl - Via Leonardo da Vinci 16, 10126, Torino, Italy - VAT 10816460017 - All rights reserved