homework 5 and polymorphism

Subject: homework 5 and polymorphism
From: John Sung (john_j_sung@yahoo.com)
Date: Wed Feb 20 2002 - 14:02:20 EST

From some of the questions that I have gotten I
believe that some of the people don't have how
polymorphism works down pat. So, I'll explain the
concept of polymorphism in relation to method calls
and how visitor pattern works.

If you had these class definitions:

class A {
  void foo() { System.out.println("A"); }

class B {
  void foo() { System.out.println("B"); }
  void bar(A a) { a.foo(); }

And if you had these statements in some other place:

A a = new A();
B b = new B();


The output of the program would be this:

There are couple things going on here in the statement
b.bar(b);. Basically, the compiler attempts to match
bar with the type B, but it doesn't find it. However
it does find parameter with type A. Since, there's a
is-a relationship between A and B, you can interchange
b with type A. This is what we call implicit casting.

Now, in the method bar(), we only have a reference to
an object of type A and we call foo() on that object.
The compiler does some tricks to resolve the method
call to the one defined in B instead of the one
defined in A. The compiler does this because the
object is really of type B and not of type A. B just
acts similar to A, i.e. have the same methods defined.

This pattern occurs twice at the same time during a
travesal. First, in the actual traversal method and
the second time for the visitor inheritance tree.

Let's say we have this class graph:

A = <b> B.
B : <c> C | <d> D *common* <f> F.
C = .
D = .
F = .

And object graph looks like this:

A -> B <:- C
       -> F
Assume that there's traverse(Visitor v) method defined
for all classes. When A calls b.traverse(v), the
actual method that's being called is the one defined
in C and not in B. It's because of the example given
above. But since the object F is defined in B and not
in C so that whole tree is not traversed.

so, you need to use a little feature called super in
java. You can do either super.traverse(v) or just
super(v). They both should work. This just allows you
to call the method defined in the super class of it.
So, if you put this in C's traverse method, it'll call
B's traverse method and B's traverse method will call
F's traverse method.

Now, the second time this pattern occurs is when you
have the before and after methods for the visitors.
You have this inheritance relationship:

Visitor : PrintingVisitor

And each of these has before and after methods for all
the classes defined in the previous class dictionary.

C.traverse() {
v.before(this) ;

In this call in C, the before method that gets called
to v, an instance of Visitor, the actual method that
gets called is the one in PrintingVisitor, because
PrintingVisitor over-rides the before(C c) method
defined in Visitor.

This particular relationship allows you to have only 1
traverse method defined for all classes and have 3
visitor classes for print(), display(), and countG().
Remember that traversal + visitor = work done. The
traversal can be reused in this particular case.

so, for part one, you should only have traverse method
defined for all classes and only 1 method for print(),
display() and countG() defined in A to start the
traversal. i.e. instantiate the correct visitor and
call a.traverse(v).

So, if you are defining print(), display(), and
countG() on all of the classes, you're not doing this
assignment correctly. As, some of you have noticed
that if you do this, most of the code are very
similar, infact, they are the same. Only difference is
the fact that you're using different visitors. So, you
use inheritance to factor out these commonalities and
only have one traverse() method instead of 3 methods
all over the class graph.

Hope this helps.

Do You Yahoo!?
Yahoo! Sports - Coverage of the 2002 Olympic Games

This archive was generated by hypermail 2b28 : Wed Feb 20 2002 - 14:02:28 EST