




Study with the several resources on Docsity
Earn points by helping other students or get them with a premium plan
Prepare for your exams
Study with the several resources on Docsity
Earn points to download
Earn points by helping other students or get them with a premium plan
This is a second midterm exam for cs164, a university course on object-oriented programming. The exam covers topics such as prototype-based inheritance, implementation of object constructs, adding and calling super, iterators and lists, and static typing. The exam consists of three questions, each with multiple parts, and students have 1 hour and 20 minutes to complete it. The exam is closed book, but students may refer to two pages of handwritten notes. Solutions will be graded on correctness and clarity.
Typology: Exams
1 / 8
This page cannot be seen from the preview
Don't miss anything!





Dec 3, 2009
This question asks you to develop an object system with prototype-based inheritance. You can (but don't have to) describe the solution you used in your project. This question also asks you to go beyond what you were required to implement in the project.
Part 1: Client code [9 points]
You may find it easier to first answer Part 2, where you implement the object system. In this part, you will use the system.
Write a code fragment in your 164 language that creates a prototype named Foo that contains fields x and y. Make the default values of x and y be 0.
Write a code fragment that creates a prototype Bar that is a "subclass" of Foo and contains a field z. Make the default value of z be 1.
Write a code fragment that creates an instance of Foo and an instance of Bar.
Add an instance method f(a) to Foo that returns the sum of x, y, and a.
Call the method f on your instance of Bar with the argument 42.
Part 4: Calling super [9 points]
Add to prototype Bar a method f(a) that adds the value of the field z to the value of the call to the same method in the superclass of Bar. The method f(a) must be written in your 164 language. Here is this method in Java:
class Bar extends Foo { ... int f(int a) { return super.f(a) + this.z; } ... }
Add a constructor to Bar that calls the constructor of its superclass and then initializes z to the sum of x and y. In Java, this would look like:
class Bar extends Foo { ... Bar() { super(); this.z = this.x + this.y; } ... }
In this question, you will build on your implementation of lists from Project 3. You will add the ability to concatenate lists.
Part 1 [6 points]
Consider the following program in the 164 language.
def range(min,max) { min = min - 1 lambda() { if (min < max) { min = min + 1 } else { null } } }
def v1 = [2*n for n in range(4,7)] // this is a list comprehension def v2 = [n/2 for n in v1]
Part 2 [17 points]
Implement function concat1(x,y) that concatenates x and y. The arguments x and y could be either lists or iterators. The result of concat1(x,y) must be a list. If x and y are lists, these lists cannot be modified by concat1; instead, the result is a new list. Assume that append(lst,elmnt), for i in e { S }, list comprehensions and coroutines are available to you. You may not modify the interpreter. Example:
def lst = concat1(v1,range(0,1)) # lst has value [8, 10, 12, 14, 0, 1] print lst[2] # outputs 12
Your code for concat1:
Consider the following Java program, which outputs "A A B". The first "A" indicates that, according to Java semantics, the methods B::f and C::f do not override the method A::f. Instead, they are considered to be unrelated methods (as if they were not even named f).
These methods are considered not to override A::f because the types of their parameters differ from that of A::f. As a result, an instance of class B has two methods: f(A x) and f(B x). The former is inherited from class A.
This question asks why Java's designers decided that B::f and C::f do not override A::f.
class A { int a; void f(A x) { System.out.println("A"); } }
class B extends A { int b; void f(B x) { System.out.println("B"); x.b = 100; } }
class C extends A { A c; void f(C x) { System.out.println("C"); } }
class Main { public static void main(String[] args) { A aa = new B(); aa.f(new B()); // in Java, this prints "A" B bb = new B(); bb.f(new A()); // in Java, this prints "A" bb.f(new B()); // in Java, this prints "B" // <your code for question 2 goes here> } }
Part 1 [6 points]
Suppose we define the semantics such that that B::f and C::f do override A::f. That is, given x.f(y), the method f to call is determined by the dynamic type of x. For example, if the dynamic type of x is B, then B::f is invoked.
What would the output of the above program be under these semantics?
Part 2 [14 points]
Consider again the modified semantics given in Part 1. Add code to the main method that, when executed, would violate the invariant that the static type system seeks to maintain.
Hint: It may help you to draw how instances of classes A, B, and C are laid out in memory.
Hint: Java does not check the types of method arguments at runtime.
Write the inserted code here.
Which variable or object field violates the invariant?
Describe in prose how this violated invariant allows you to do something bad.