This exam is open book, open notes. You are to work independently. 71 points total.
abstract class Plant { // return true if this plant has chlorophyll abstract public boolean hasChlorophyll(); public String description() { return "a plant."; } } class Tree extends Plant { // height of this tree in feet private int height; public Tree (int height) { this.height = height; } public String description() { return "a tree " + height + " feet tall. also " + super.description(); } public boolean hasChlorophyll() { return true; } static public String hardness() { return "unknown"; } }
class Oak extends Tree { public Oak (int height) { super(height); } public String description() { return "an oak. also " + super.description(); } static public String hardness() { return "very hard"; } } class Cedar extends Tree { public Cedar (int height) { super(height); } public String description() { return "a cedar. also " + super.description(); } static public String hardness() { return "soft"; } } class Mushroom extends Plant { public String description() { return "a mushroom. possibly poisonous, so watch out. also " + super.description(); } public boolean hasChlorophyll() { return false; } }
Now suppose we also have a class PlantTest with a main method. What is the result of compiling and executing the Java program for each of the following versions of PlantTest and main? The result might be that the program runs correctly, or it might have a compile time error, or a runtime error. If the program compiles correctly and can be run, give the output. Otherwise explain what the error is.
public class PlantTest { public static void main (String [ ] args) { Plant p = new Plant(); System.out.println(p.hasChlorophyll()); System.out.println(p.description()); } }
PlantTest.java:4: class Plant is an abstract class. It can't be instantiated. Plant p = new Plant(); ^ 1 error Compile Error
public class PlantTest { public static void main (String [ ] args) { Plant p = new Mushroom(); System.out.println(p.hasChlorophyll()); System.out.println(p.description()); } }
Running... false a mushroom. possibly poisonous, so watch out. also a plant.
public class PlantTest { public static void main (String [ ] args) { Oak o = new Oak(150); Tree t = o; System.out.println(o.description()); System.out.println(t.description()); System.out.println(o.hardness()); System.out.println(t.hardness()); } }
Running... an oak. also a tree 150 feet tall. also a plant. an oak. also a tree 150 feet tall. also a plant. very hard unknown
public class PlantTest { public static void main (String [ ] args) { Oak o = new Oak(150); Tree t = (Tree) o; System.out.println(t.description()); } }
Running... an oak. also a tree 150 feet tall. also a plant.
public class PlantTest { public static void main (String [ ] args) { Tree t = new Oak(150); Oak o = (Oak) t; System.out.println(o.description()); } }
Running... an oak. also a tree 150 feet tall. also a plant.
public class PlantTest { public static void main (String [ ] args) { Tree t = new Cedar(200); Oak o = (Oak) t; System.out.println(o.description()); } }
Running... java.lang.ClassCastException: Cedar at PlantTest.main(PlantTest.java:4) Runtime Exception
(define a 100) (define b 200) (define (test1) (let ((a 5) (b (+ a 3))) (+ a b))) (define (test2) (let* ((a 5) (b (+ a 3))) (+ a b)))
Then what is the result of evaluating the following Scheme expressions? If there is an error say so. Write your answer using the printable representation of the result (i.e., what the Scheme system outputs after evaluation).
;Value: 300
;Value: 108
;Value: 13
;Value 1: (2 4 6)
(define (squid x y) (+ x y)) (define (clam n) (squid (* 2 n) 20))
Suppose we evaluate the expression (squid 3 4) using the metacircular evaluator that you worked on for your Scheme project. The result is 7.
The environment that the interpreter uses when evaluating the expression (+ x y) is:
( ((x y) 3 4) ((squid clam + * false true car cdr cons null?) ...) )
There are two frames in the environment. The first frame in the environment has bindings for x and y (which are bound to 3 and 4 respectively). The second frame contains the global variables and their bindings (which I just indicated by ...).
Suppose we evaluate the expression (clam 100). What is returned?
;Value: 220
While evaluating (clam 100), what is the environment that the interpreter uses when evaluating the expression (* 2 n) in the clam function? (You can abbreviate the global environment as above.)
( ((n) 100)
((squid clam + * false true car cdr cons null?) ...)
)
Still while evaluating (clam 100), what is the environment that the interpreter uses when evaluating the expression (+ x y) in the squid function?
( ((x y) 200 20)
((squid clam + * false true car cdr cons null?) ...)
)
Now suppose we've defined yet another pair of functions:
(define (test n) (helper n n)) (define (helper a b) ((lambda (a) (+ a b)) 42))
Suppose we evaluate the expression (test 100). What is returned? What is the environment that the interpreter uses when evaluating the expression (+ a b), in other words the environment used when evaluating the body of the lambda after it has been applied to its argument?
( ((a) 42)
((a b) 100 100)
((helper test squid clam + * false true car cdr cons null?) ...)
)
General Discussion:
The Java implementers did not want to allow multiple inheritance for classes
because super-classes could then have conflicting methods and instance
variables. Multiple inheritance has however, proven to be useful for
polymorphism (We want one particular class to be able to be passed to several
different methods, each expecting this class have a specific programming
interface). The solution, interfaces, that do not inherit functionality
but guarantees that the class provide the required programming interface.
For this reason Java's designers added interfaces to the Java languages.
Abstract classes can be used to give several classes shared ancestry and
shared implementation of a subset of their member functions. Abstract
classes are often used when it makes no sense to ever have an instance of
the object, but subclasses have a common behavior (and thus implementation).
The common implementation for the classes can then go into their
abstract base class.
A prime
example of this is the InputStream abstract class. The InputStream has methods, int read(), int
read(btye[], int read(byte[],int,int), and others. Of all of these
methods, only read() is abstract. Note that read(btye[]) and
read(byte[],int,int) methods call read() by default. A subclass
could choose to override these, but they do not have
to override them. The other non-abstract
methods on InputStream default to intelligent things. For example, the
void close() method does nothing. For more details, see the JDK
documentation.
Key Points: