0% found this document useful (0 votes)
8 views12 pages

Oop 4

The document provides a comprehensive overview of Java concepts such as inheritance, polymorphism, and method overriding through various class examples. It includes detailed explanations of how different classes interact, the output of specific code snippets, and the implications of variable shadowing and access modifiers. Additionally, it presents a skeleton for a Robot class and poses a question regarding its functionality when completed.

Uploaded by

Ace Leo
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
8 views12 pages

Oop 4

The document provides a comprehensive overview of Java concepts such as inheritance, polymorphism, and method overriding through various class examples. It includes detailed explanations of how different classes interact, the output of specific code snippets, and the implications of variable shadowing and access modifiers. Additionally, it presents a skeleton for a Robot class and poses a question regarding its functionality when completed.

Uploaded by

Ace Leo
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 12

Practice Problems: Inheritance & Polymorphism

public class Foo {


public void method1() {
System.out.println("foo 1");
}
public void method2() {
System.out.println("foo 2");
}
public String toString() {
return "foo";
}
}
public class Bar extends Foo {
public void method2() {
System.out.println("bar 2");
}
}

public class Baz extends Foo {


public void method1() {
System.out.println("baz 1");
}
public String toString() {
return "baz";
}
}
public class Mumble extends Baz {
public void method2() { baz
System.out.println("mumble 2"); baz 1
} foo 2
}
foo
public class Polymorphism{ foo 1
public static void main(String [] args){ bar 2
Foo[] pity = { new Baz(), new Bar(),
new Mumble(), new Foo() }; baz
for (int i = 0; i < pity.length; i++) { baz 1
System.out.println(pity[i]); mumble 2
pity[i].method1();
pity[i].method2(); foo
System.out.println(); foo 1
} foo 2
}
*( ) method is inherited. Otherwise, method is overridden.

1. Tracing programs: The above is the program demonstrated in class.


Now, what gets printed to the screen when we execute the following
classes on the left?
public class A { Result:
public int x = 1; 1
public void setX(int a){ 2
x=a;
} Public instance variable and
} instance method can be
public class B extends A { inherited and accessed by
public int getB(){ subclass (without
setX(2); overriding)
return x;}
}
public class C {
public static void main(String [] args){
A a = new A();
B b = new B();
System.out.println(a.x);
System.out.println(b.getB());
}
}
public class A { Result:
private int x = 1; 1
protected void setX(int a){ 2
x=a;
} Private instance variable
protected int getX(){ and private instance
return x;} methods can be inherited
} but not accessible to
public class B extends A { subclass!
public int getB(){
setX(2); Protected instance variable
//return x; It does not work because private modifier, so and protected instance
return getX(); methods can be inherited
} and accessible to subclass,
}
public class C {
public static void main(String [] args){
A a = new A();
B b = new B();
System.out.println(a.getX());//a.x is not allowed, private!
System.out.println(b.getB());
}
}

public class A { Result


protected int x = 1; 1
protected void setX(int a){x=a;} 1
protected int getX(){return x;} 2
}
public class B extends A { *The difference of B’s x is
public int getB(){ not variable shadowing. It’s
setX(2); the expected execution of
return x; value resetting (setX(2)).
}
}
public class C {
public static void main(String [] args){
A a = new A();
B b = new B();
System.out.println(a.getX());
System.out.println(b.x); //b.x is protected, then inherited.
System.out.println(b.getB());
}
}
public class A { Resutls:
protected int x = 1; 1
protected void setX(int a){ 3
x=a; 3
} 1
protected int getX(){ 3
return x;}
} Do you know which getX
public class B extends A { of b is called, A’s or its
protected int x = 3; own? If you cannot ensure
public int getX(){ your answer right, please
return x; } see the comment in the
public int getB(){ below.
return x;
}
}
public class C {
public static void main(String [] args){
A a = new A();
B b = new B();
System.out.println(a.getX());
System.out.println(b.getB());//subclass method access own attrib
System.out.println(b.getX());//overriding method, accessing sub
System.out.println(a.x); //protected
System.out.println(b.x); //overriding attribute!
}
}
public class A { Results:
protected int x = 1; 1
protected void setX(int a){ 3
x=a; 1
} 1
protected int getX(){
return x;} Subclass variable can be
} accessed by method, the
public class B extends A { direct access (without using
protected int x = 3; method) will reach the
public int getX(){ overridden value from
return x; } superclass!
public int getB(){
return x; b.getB is not permitted
} because it is out A’s
} signature. b.getX is allowed
public class C { because it is overridden!
public static void main(String [] args){
A a = new A();
A b = new B(); //polymorphism, making shadowing possible! // For your development:
System.out.println(a.getX()); //1) Is it good to block the
System.out.println(b.getX());//override, access subclass attri. use of b.getB()?
//System.out.println(b.getB()); not able to load subclass method! // ANS>: Good,
System.out.println(a.x); because methods can be in
System.out.println(b.x); //variable shadowing! template. In the security
} control, no leakage!
} //2) Is it good to have the
direct access of attribute
such as b.x?
// ANS>: Better not,
if it is not in your control.
See how complicate it is in
this program.
public class A {
protected int x = 1; Results:
protected void setX(int a){ 1
x=a; 3
} 1
protected int getX(){ 2
return x;}
} b.x is set to 2 because a
public class B extends A { superclass method is called to
protected int x = 3; change the value of shadowed
public int getX(){ value.
setX(2); // call superclass method to set superclass attrib
return x; } //but return attrib of subclass
public int getB(){
return x;
}
}
public class C {
public static void main(String [] args){
A a = new A();
A b = new B();
System.out.println(a.getX());
System.out.println(b.getX());
System.out.println(a.x);
System.out.println(b.x);
}
}
public class Ham {
public void a() {
System.out.println("Ham a");
}
public void b() {
System.out.println("Ham b");
}
public String toString() {
return "Ham";
}
}

public class Lamb extends Ham {


public void b() {
System.out.println("Lamb b");
}
}

public class Yam extends Lamb {


public void a() {
System.out.println("Yam a");
}
public String toString() {
return "Yam";
}
}

public class Spam extends Yam {


public void a() {
System.out.println("Spam a");
}
}

public class Polymorphism2 {


public static void main (String [] args){
Ham[] food = { new Spam(), new Yam(), Yam
new Ham(), new Lamb() };
for (int i = 0; i < food.length; i++) { Spam a
System.out.println(food[i]); Lamb b
food[i].a();
food[i].b();
System.out.println(); Yam
} Yam a
}
}
Lamb b

Ham
Ham a
Ham b

Ham
Ham a
Lamb b
public class Ham {
int a = 0;
ÏϧÏHam 0 1
int b = 1; ÏϧÏSpam 2
public void a() {
System.out.println("Ham “ + a);
ÏϧÏHam1
} ÏϧÏ0
public void b() {
System.out.println("Ham “ + b); ÏϧÏ1
} ÏϧÏ
public String toString() {
return "Ham “ + a + “ “ + b; ÏϧÏHam 0 1
} ÏϧÏYam 2
}
ÏϧÏYam 3
public class Spam extends Ham { ÏϧÏ0
int a = 2;
public void a() { ÏϧÏ1
}
System.out.println("Spam “ +a); ÏϧÏ
} ÏϧÏHam 0 1
public class Yam extends Spam {
ÏϧÏHam0
int b = 3; ÏϧÏHam1
public void a() {
System.out.println("Yam “ + a); ÏϧÏ0
} ÏϧÏ1
public void b() {
System.out.println(“Yam “ + b);
}
}

public class Polymorphism3 {


public static void main (String [] args){
Ham[] food = { new Spam(), new Yam(),
new Ham()};
for (int i = 0; i < food.length; i++) {
System.out.println(food[i]);
food[i].a();
food[i].b();

System.out.println(food[i].a);

System.out.println(food[i].b);
System.out.println();
}
}
}
public class A public class C extends A
{ {
private String x = "Ax"; private String x = "Cx";
protected String y = "Ay";
public String z = "Az"; public static void main(
String [] args)
public String toString() { {
return x + y + z; C c = new C();
} System.out.println(c.x);
System.out.println(c);
public static void main( }
String [] args) }
{
A a = new A(); public class D extends C
System.out.println(a); {
} private String x = "Dx";
} public String z = "Dz";

public class B extends A public static void main(


{ String [] args)
private String x = "Bx"; {
public String z = "Bz"; D d = new D();
System.out.println(d.x);
public String toString() { System.out.println(d.y);
return x + y + z; System.out.println(d.z);
} System.out.println(d);

public static void main( C c = new D();


String [] args) // Error: System.out.println(c.x);
{ System.out.println(c.y);
B b = new B(); System.out.println(c.z);
System.out.println(b); System.out.println(c);
} }
} }

When A is executed, it displays:


AxAyAz
The println statement implicitly calls a.toString(), which creates a string containing the
concatenation of the variables x, y, and z. Once this concatenated String ("AxAyAz") is
returned, it gets printed to the screen.

When B is executed, it displays:


BxAyBz
The println statement implicitly calls b.toString(), which refers to the overriding toString()
method defined in subclass B. This toString method says to concatenate x+y+z (like the one
defined in class A), but now it is referring to variables x, y, and z in the B class. Two of those
variables are defined locally – x and z. These variables hide (or "shadow") the x and z variables
defined in class A. The third variable, y, is inherited from A. As a result, the concatenation in
the toString method produces a String that looks like "BxAyBz", which then gets printed.

When C is executed, it displays:


Cx
AxAyAz
When the first println statement executes, it refers directly to c.x, which is defined locally. So
that prints out "Cx".
When the second println statement executes, it refers to C's inherited toString method. The
inherited toString method is defined in class A, which returns the concatenation of x, y, and z
from class A. So that returns "AxAyAz", which gets printed.

When D is executed, it displays:


Dx
Ay
Dz
DxAyDz
Ay
Az
DxAyDz
The first 3 lines print the values of x, y, and z inside of d. Since x and z are defined inside of
class D, those values get printed out. y is inherited from class A, so "Ay" gets printed out.

The next line prints the return value of D's toString method. The toString method is defined
locally to override the inherited one (unlike in the example for class C, where the toString
method is inherited instead of overridden). Because the toString method is overridden, when it
refers to x, y, and z, it refers to the variables inside of class D. So this returns "DxAyDz".
Compare this to the inherited toString method in class C, which returns "AxAyAz".

The next two lines use a variable with static type C to refer to an object of dynamic type D.
Notice that it is an error to try to print (or refer to) c.x. That's because 'x' is private in class C,
and this code is written inside class D. Also notice that c.z is "Az", whereas d.z is "D.z". For
fields, Java uses the value of the static type's field (in this case, the value of z from class C,
which is inherited from class A and has value "Az").

The last line prints the value of c.toString(). Java uses the value of a the static type's field, but
the dynamic type's methods. Variable c has dynamic type D, because it refers to an object of
type D. So Java uses the toString method defined in class D, which returns the values of x, y,
and z within class D (or "DxAyDz"). Notice the difference between how fields get handled, and
how methods get handled. The field c.z refers to the field defined in class C (which is inherited
from class A). The method c.toString() refers to the method defined in class D, not class C.

I have still not figured out any reason why Java does shadow things this way for fields. It's very
confusing, and it can lead to very hard-to-fix bugs. In general, it is HIGHLY RECOMMENDED
that you AVOID defining fields with the same name as a superclass's field. Sometimes though
(like when you're extending a superclass from the Java API), you may not know what the
superclass's fields are called, and in that case, you just have to guess.

2. Program Development
Here's a problem from a previous Final Exam.

Consider the following skeleton for a Robot class, which has private fields for storing the
location of aRobot object, its name, and the direction it’s facing (North for a direction parallel to
the positive y axis,South for the negative y axis, East for the positive x axis, or West for the
negative x axis). It also hasstub methods for constructing a Robot object, changing the direction,
and moving the location of therobot in the direction it’s facing.

public class Robot


{
private String name;

private char direction; //’N’,’S’,’E’, or ’W’

privateintxLoc, yLoc; // the (x, y) location of the robot

// Initialize name, direction, and (x, y) location


public Robot(String name, char dir, int x, int y) { ... }

public String toString()


{
return name + " is standing at (" + x + "," + y + ") and facing"
+ direction);
}

// turn 90 degrees clockwise, e.g. ’N’ changes to ’E’, ’E’ to ’S’, ...
public void turnClockwise() { ... }

// turn 90 degrees counterclockwise, e.g. ’N’ to ’W’, ’W’ to ’S’, ...


public void turnCounterClockwise() { ... }

// move numSteps in direction you are facing,


// e.g. if ’N’ 3 steps, then y increases 3
public void takeSteps(intnumSteps) { ... }
}

(a)Assuming the class above is completed correctly, what does the following program display
on the screen:

public static void main(String args[])


{
Robot robby = new Robot("Robby", ’N’, 10, 12);
for (inti = 0; i< 5; i++)
{
if (i % 2 == 0)
{
robby.turnClockwise();
}
else
{
robby.turnCounterClockwise();
}

robby.takeSteps(3);
System.out.println(robby);
}
}
Displayed on screen:

Robby is standing at (13, 12) and facing E


Robby is standing at (13, 15) and facing N
Robby is standing at (16, 15) and facing E
Robby is standing at (16, 18) and facing N
Robby is standing at (19, 18) and facing E

(b) Complete the constructor, the turnClockwisemethod, and the takeStepsmethod. Make sure
your constructor validates its input. You do not need to define turnCounterClockwise.

public Robot(String name, char dir, int x, int y)


{
this.name = name;
this.direction = dir;
this.xLoc = x;
this.yLoc = y;
}

public void turnClockise()


{
if(direction=='N') { direction = 'E'; }
else if(direction=='E') { direction = 'S'; }
else if(direction=='S') { direction = 'W'; }
else { direction = 'N'; }
}

public void takeSteps(int numSteps)


{
if(direction=='N') { yLoc += numSteps; }
else if(direction=='E') { xLoc += numSteps; }
else if(direction=='S') { yLoc -= numSteps; }
else { xLoc -= numSteps; }
}

(c) Write Java code to create an array of 5 robots. Use a for loop to fill in the array so that the n-th
robot is named “robot n”, and it starts off life facing east at location (n, n).

Robot [] robots = new Robot[5];


for(int i=0; i<robots.length; i++)
{
robots[i] = new Robot("robot " + i, 'E', i, i);
}

Here's another problem from a previous Final Exam. This one is an inheritance/polymorphism
question.
classSuperClass
{
protectedint x = 0;

publicSuperClass(int x)
{
this.x = x;
}

private void increment() { x++; }

protected final void add(int y)


{
x += y;
}

public void display()


{
System.out.println(x);
}
}

public class SubClassextends SuperClass


{
publicSubClass(int x)
{
super(x);
}

public void display()


{
add(2);
super.display();
}

public static void main(String [] args)


{
SuperClasssc = new SuperClass(3);
sc.display();

sc = new SubClass(3);
sc.display();
}
}

(a)List the name of all methods that subclasses of SuperClass inherit.


subclasses inherit all methods: the constructor, increment, add, and display. If you want, you
could also list all of the methods that SuperClass implicitly inherits from the Object class (eg,
equals, toString, etc.), but that's not required.

(b)List the name of all methods that are visible in subclasses of SuperClass (in other words,
methodsthat can be called directly).

add can be called directly just be using the name add(). the constructor SuperClass can be
called by using the super() constructor. the display() method from SuperClass is overridden by
the display() method in the SubClass, but it can still be called by writing super.display(). In
summary, any method that has public or protected access in the superclass can be called directly
by the subclass.

(c)List the name of all methods that may NOT be overridden by any subclasses of SuperClass.

methods that are declared to be final in the superclass may not be overridden. So the add()
method may not be overridden.

(d)What gets displayed on the screen when SubClass is executed?

displayed on screen:

3
5

You might also like