Worksheet: J2 | CS 2113 Software Engineering - Spring 2022

Worksheet: J2

Worksheets are self-guided activities that reinforce lectures. They are not graded for accuracy, only for completion. Worksheets are due by Sunday night before the next lecture.

Note

Attempt to answer these questions before running the code. This will improve your ability to analyze and reason about code without an IDE or compiler. This skill we be helpful on the exams.

Questions

  1. Define polymorphism in the context of Java and provide one example where it is valuable?

  2. Consider the following program from the class notes

    public class Ex3 {
      public static void main(String[] args) {
        Random   rand = new Random(System.currentTimeMillis());
        Point    v    = new Point(3, 4);
        LabPoint w    = new LabPoint(5, 2, "A");
        String   x    = "I'm a string";
        Scanner  y    = new Scanner(System.in);
    
        Object u;
        int i = rand.nextInt(4);
    
        if( i == 0 )
          u = v;
        else if( i == 1 )
          u = w;
        else if( i == 2 )
          u = x;
        else
          u = y;
        System.out.println(u); //<--
      }
    }
    

    Explain how polymorphism makes this program possible.

  3. What is the output of this program? You should be able to do this without running the program!

    class A {
        public String toString(){
            return "A";
        }
    }
    
    class B extends A{
        public String toString() {
            return "B";
        }
    }
    
    class C extends A {
        public String toString() {
            return super.toString();
        }
    }
    
    class D extends C {
        public String toString() {
            return super.toString();
        }
    }
    
    public class tmp{
        public static void main(final String args[]) {
            D d = new D();
            System.out.println(d.toString());
        }
    }
    

  4. What is the output of this program? You should be able to do this without running the program!

    class A {
        public String toString(){
            return "A";
        }
        
        public String fancyToString() {
            return "~~A~~";
        }
    }
    
    class B extends A{
        public String toString() {
            A letterA = this;
            return letterA.fancyToString();
        }
        public String fancyToString(){
            return "~~B~~";
        }
    }
    
    public class LetterPrinter{
        public static void main(final String args[]) {
            B letterB = new B();
            System.out.print(letterB.toString()+ " ");
            
            A letterA = letterB;
            System.out.println(letterA.toString());
        }
    }
    

  5. What is the output of this program? You should be able to do this without running the program!

    class A {
        public String toString(){
            return "A";
        }
        
        public String fancyToString() {
            return "~~A~~";
        }
    }
    
    class B extends A{
        public String fancyToString(){
            return "~~B~~";
        }
    }
    
    public class LetterPrinter{
        public static void main(final String args[]) {
            B letterB = new B();
            System.out.print(letterB.toString()+ " ");
            
            A letterA = letterB;
            System.out.println(letterA.toString());
        }
    }
    

  6. Consider the first 2 class declarations. What is the output of the program below? You should be able to do this without running the program!

    abstract class Letter {
        protected boolean uppercase;
    
        abstract String get_name();
    
        abstract int get_alphabet_position();
    }
    
    class A extends Letter{
        public String toString() {
            return "A";
        }
    
        protected int get_alphabet_position() {
            return 1;
        }
    
        private String get_name() {
            return "A";
        }
    }
    
    public class Main{
        public static void main(final String args[]) {
            A a = new A();
            System.out.println("A: " + a.get_alphabet_position());
        }
    }
    
    

  7. If we change the implementation of A to the following, how does that change the output?

    class A extends Letter{
        public String toString() {
            return "A";
        }
    
        public int get_alphabet_position() {
            return 1;
        }
    
        protected String get_name() {
            return "A";
        }
    }
    

  8. What is the output of this program? You should do this without running the program.

    class A{
        public String toString(){
            return "A";
        }
    }
    class B extends A{
        public String toString(){
            return "B";
        }
    }
    public class PolymorphicOverload{
        public void foo(B letterB1, B letterB2) {
            // 2
            System.out.println("foo2: " + letterB1 + " " + letterB2);
        }
    
        public void foo(A letterA1, A letterA2){
            //1
            System.out.println("foo1: " + letterA1 + " " + letterA2);
        }
        public static void main(String args[]){
            PolymorphicOverload f = new PolymorphicOverload();
            B letterB = new B();
            A letterA = (A) new B();
            f.foo(letterB, letterA);
        }
    }
    

  9. Assume that class A is implemented in such a way so that the program will compile and run. What is the output? You should do this problem without running the code.

    public class tmp{
        public static void foo(A a){
            System.out.println("foo1: "+a.get_name());
        }
        public static void foo(Letter a) {
            System.out.println("foo2: " + a.get_name());
        }
        public static void main(final String args[]) {
            Letter a =(Letter) new A();
            foo(a);
        }
    }
    

  10. Suppose you had the following class structures

    public class Species{
        String genus;
        String species;
        public Species(String g, String s){genus=g;species=s;}
        public Species(Species s){genus=s.genus;species=s.species;}
        String toString(){return genus+" "+species;}
    }
    
    public class Breed extends Species{
        protected String breed;
        public Breed(String b, String g, String s){
            super(g,s);
            breed=b;
        }
        public Breed(String b, Species s){
            super(s);
            breed=b;
        }
        String toString(){super.toString() + "("+breed+")";}
    }
    
    public class Pet{
        String name;
        Species species;
        public Pet(String n, Species s){
           name=n;
           species=s;
        }
        String toString(){
            String ret = "Name: "+name+"\n";
            ret += "Species: "+species;
            retunr ret;
        }       
    

    What is the output of the following snippet of code? If there is an ERROR, describe the error. You should not need to run the code to determine the output.

        
       Species dog = new Species("Canis","Familaris");
       Breed shorthair = new Breed("shorthair",new Species("Felis","Catus");
       Pet fluffy = new Pet("fluffy", new Breed("pomeranian", dog);
       Pet george = new Pet("george", dog);
       Pet brutus = new Pet("brutus", (Species) shorthair)
       
       System.out.println(fluffy);
       System.out.println(george);
       System.out.println(brutus);
    

  11. Consider the following classes

    public class A{
        public int foo(){return 42;}
        public int bar(){return foo()+8;}
    }
    
    public class B extends C{
        public int foo(){return 41;}
        public char baz(){return "y";}
    }
    
    public class C extends A{
        public char baz(){return "x";}
    }
    
    public class D extends A{
        public int bar(){return 7;}
    }
    
    public class E extends C{
        public int bar(){return foo()+20;}
    }
    
    

    Draw the class hierarchy for the above classes, that is the UML diagram that simply shows who inherits from whom.

  12. Continuing with the classes from the previous question, consider a mystery function that returns a object of the given class. You do not know the definition of the mystery function, other than it compiles properly and returns an object of the class. For each of the following method calls marked below, indicate the value of the output, if the output cannot be determined, or if there is an error.

    
    A a = mysteryA(); //<-- mystery function, this line compiles (the below may not!)
    System.out.println(a.foo()); //<-- Mark A.1
    System.out.println(a.bar()); //<-- Mark A.2
    System.out.println(a.baz()); //<-- Mark A.3
    
    
    B b = mysteryB(); //<-- mystery function, this line compiles (the below may not!)
    System.out.println(b.foo()); //<-- Mark B.1
    System.out.println(b.bar()); //<-- Mark B.2
    System.out.println(b.baz()); //<-- Mark B.3
    
    D d = mysteryD(); //<-- mystery function, this line compiles (the below may not!)
    System.out.println(d.foo()); //<-- Mark D.1
    System.out.println(d.bar()); //<-- Mark D.2
    System.out.println(d.baz()); //<-- Mark D.3
    

  13. What is the difference between a class and an abstract class?

  14. If you were to create an abstract class for a Car – what features could be defined in the implemented class vs. what could be defined in the abstract class? Provide justifications for your design.