CS Lecture-Module #03:
Extending Classes a.k.a. Inheriting among Classes


motivation: 
suppose wrote a method for some basic class;
conceivably, other classes might actually want same functionality

could copy the original code
    class Class0 {
        m() {
            .
            .       // lots of code --- |if|s and |for|s ...
            .
            }
        }

    class Class2 {

        }

    class Class3 {

        }

    ...

    main() {
        ...
        obj2.m();
        obj3.m();
        ...
        }
but later if you determine how to do things better,
you'd have to update each copy of the code the same way

could put code in method (say m()) of class (say Class0), have others invoke the method
as with library functions such as  sqrt()  in  Math class, drawRect()  in  Graphics class
but if the purpose is to process nontrivial data then would have to pass it all the time
    m(big_arraylong_Stringseveral_ints...);
   

plus if want another class Class2 to actually have such a method m()
so could invoke for a Class2 object obj2.m()
would need to arrange chaining:
Class2 with method m() which does nothing but invoke Class0's m()
    class Class0 {
        m() {
            .
            .       // lots of code --- |if|s and |for|s ...
            .
            }
        }

    class Class2 {
        m() {
            Class0.m();
            }

    class Class3 {
        m() {
            Class0.m();
            }

    ...

    main() {
        obj2.m();
        obj3.m();
        ...
        }


solution: extending class a.k.a. inheriting simply gives the method




to some extent also do reuse of data-organization
but that's easy even without inheritance:

term for this: 



two mechanisms for code reuse with inheritance:
1. inherit code, data
sub-classes can use code and data-organization written for super-classes instead of needing to write again
e.g. if a  class Monster  has method chase(),
won't need to write  chase()  again inside  class Leprechaun  and  class Hobgoblin ...
the latter classes will  from  class Monster:
class Monster {
    chase() {
        .
        .       // here fully coded
        .       // using |if|s and |for|s etc.
        .
        }
    }

class Hobgoblin ... {
    attack() { ... }    // damages player
    no definition of  chase()
    }

class Leprechaun ... {
    attack() { ... }    // steals player's gold
    no definition of  chase()
    }

class Suite ... {
    ...
    Hobgoblin h;
    Leprechaun l;
    h.attack(); // 
    l.attack(); // 
    h.chase();  // 
    l.chase();  // 
    ...
    }
2. 
code written to work on objects of one type
will work on objects of other types (specifically sub-types)
i.e. objects of different forms   'poly' 'morph'
e.g.:
Monster[] monsters = new Monster[...];
int num_monsters;
monsters[0] = new Leprechaun(...);
monsters[1] = new Hobgoblin(...);
...

for( int i = 0; i < num_monsters; i++ )
  {
  monsters[i].chase();  // 
  monsters[i].attack(); // 
  // 
  // 
  }


details:
inheritance starts with a base-class:
class B {
    ...


second class inherits from that base-class
class D  B {
    ...


e.g.:
class Monster {
    field_variables
    methods such as chase()
    }

class Hobgoblin  Monster {
   // don't define chase() -- inheriting that from |Monster|
   attack() { ... }
   }

class Leprechaun  Monster {
   similarly
in such a situation,
B  called 
and inheriting class (D) called 
e.g.:
class B {
     int z, y = 8;

    public int f() {
        return  3 * y;
        }

    public void set_z(int z_new) {
        z = z_new;
        }
    }

class D extends B {
    private int x;

    public int g() {
        return  4 + x;
        }

    public void  h() {
        set_z(5);    // 
         y = 6;         // 
        }
    }

// code outside those classes:
B b1 = new B();

    b1:
    +---------+
    | int z   |
    | int y   |
    | f()     |
    | set_z() |
    +---------+

int  w;
w = b1.f();

B b2 = new B();

    b2:
    +---------+
    | int z   |
    | int y   |
    | f()     |
    | set_z() |
    +---------+

D d1 = new D();

    d1:
    +-------------+
    | int x       |
    | g()         |
    | h()         |
    | + - - - - + |
    | . int y   . |
    | . int z   . |
    | . f()     . |
    | . set_z() . |
    | + - - - - + |
    +-------------+

w = d1.g();
w = d1.f();      // 
d1.h();

but rem. can't directly access  x  or  y  or  z  if they're declared  private
d1.x = 8;        // 

b1.y = 7;        // 
even inside  D  can't directly access  y  or  z  if they're declared  private!
conceptually this is weird:
from  B,  d1  inherits  y,  z
and can access and affect them with  public  methods
    e.g. f(),  set_z()
but  d1  can't access its  y,z  directly
think of a  B  object inside  d1  but with a shell around it

solution:
declaring  B  instance-variable  would give sub-class (D) access but outside code not (? ;-}
protected  is another access-modifier like publicprivate
specifies 'outside' code still can't access but inheritors can

but since 'outside' code could whenever desired gain access to a  protected  member by writing inheriting code,
I deprecate  protected                                  for fields i.e. instance-variables
just use  private  and methods
with modern compilers, this should be just as efficient as direct access
and retains safety of  private  protection



Java restricts: can't extend more than one class
    other languages (C++) allow multiple extension
    problematic: suppose a class inherits from two classes
    and each of those two classes has a method attack()
    but one damages the player and the other steals some of the player's gold
    which of the two behaviors will the inheriting class get?
    one? both? neither?
    handling such conflicts makes things inefficient
    and always can do the code otherwise
    so designers of Java simply avoided providing this

    multiple interfaces OK
    e.g.   ...  implements ActionListener, MouseListener
    you're simply promising to implement interfaces' methods
    can't really have conflicts
    e.g. if one interface specifies having a method clear()
    and another interface specifies having a method clear()
    and you want to implement both of them
    just have a method clear()  and you've satisfied them
    no conflict



constructor:
actually don't exactly inherit constructors
so inside constructor of derived/sub-class,
if want to invoke constructor of -class,
in first line have:    super(parameters);
e.g.:
class B {
  private int y, z;
  public B(int y0, int z0) { y = y0; z = z0; }
  }
class D extends B {
  private int x;
  public D(int x0, int y0, int z0) {
    
    x = x0;
    }
  }
in fact derived class's constructor must do this
unless base class has a no-argument constructor or no constructor
e.g.  new D()  automatically chains  new B()



though inherit super-class's methods, may want to do things differently
e.g. class  Monster  could have basic  attack() method:
    class Monster {
        attack() { ... }        // basic hurting player
        chase() { ... }
        }
Leprechaun  would inherit  attack()  but wouldn't want to use it
so  it
simply write own method with same name, arguments
    class Leprechaun extends Monster {
        // override:
        attack() { ... }        // just steal gold, NOT hurting player
        // get |chase()| inherited from |Monster|
        }
if it's desired for the subclass to have its own overriding method but also sometimes invoke the super-class's method,
use "super.method(args)"
e.g.:
    class Ant extends Monster {
        // override to sting:
        attack() {
            ... // weaken player by stinging
               // but also do basic hurting
            }
        // get |chase()| inherited from |Monster|
        }
super-class could prevent overriding of a method by qualifying it with  final
e.g. this probably would be good with  chase()  considering how fundamental it is


inheritance-hierarchy

suppose you write a class  D  inheriting from B  which inherits from A
D  inherits material from  B  and  B  inherits material from  A
then among material from  B,  D  gets material from  A
thus 
thus generally, a class's superclasses include its immediate superclass
(the specific one named explicitly following the word  extends)
plus the superclass of the immediate superclass
plus the superclass of that
and so on

with other classes such as say D2  also inheriting from B,
get linked chains of classes and superclasses:
             
            .
           .
          .
         /
        A
       / \
      B   .
     / \   .
    D  D2   .
at the top of this hierarchy is the pre-supplied class Object
everything inherits from that and is a sub-class of it
even if you don't write "extends Object"
e.g.  class Monster  is a sub-class of  Object
(I deprecate writing "extends Object")





above  d1.f()     D  inheriting  f()  from  B  is basic mechanism

further can do:

polymorphism

normally can't store values of one type in variables of a different type
e.g.
String s = "hello";
int i = 4;
i = s;  // 
s = i;  // 
but can store objects of derived class in variables of base class
e.g.:
b1 = d1;  // 
Object o;
o = monsters[3];  // 
o = "hello";  // 
reflects derived object can be handled/used as base object because possesses all base features 
    ...  b1.f()  ...
    ...  b1.set_z(...)  ...
initial discussion of polymorphism above provides further example

but then considering that a variable can thus hold an object of different classes at different times,
for standard method-invocation:
    object_variable . method(arguments)
system invokes method for actual class of object stored in object_variable at the time
  "dynamic" because it's determined while the program is running
this occurs even if no object_variable is explicitly given:
    method(arguments)

but sometimes after store object of sub-class in variable of superclass
want to clarify the object's real class

one thing you could do is
check whether an object on hand is a member of a particular class via 
instanceof  is actually an operator like "+" or "<=" or "."
usage as follows:
object instanceof class_name      yields  like "<="
e.g.:    if( monsters[i] instanceof Leprechaun ) {
                        ...

but even if you know the class of an object stored in a variable of super-class,
it's not clear to the compiler
that you can use attributes of that class
e.g.:
w = b1.f();
    
w = b1.g();      
compiler knows only that  b1  is a variable of type  B
it might contain a  D  object, and  D  does have a method  g() -- but variable b1  might not contain a  D  object; might contain only plain  B object

so might want to store object back in variable of its own class:
d1 = b1;   // 
then could do:
w = d1.g();
and similarly:
String s = o;   // 
but for each of those two re-stores, 
e.g. for the latter one,
compiler doesn't know whether you last put a  String  or a  Monster  in o
(and  Monster  isn't sub-class of  String  so wouldn't be able to even polymorphically store a  Monster  in a  String variable)
what to do?
rem. what did to store floating-point value such as  14.0  in  int variable:

int i =  Math.sqrt(196);
String s =  o;



another illustration of inheritance:

c_tchrs_problem.html

incidentally, what would be "init." method(s) for classes? 


a 'solution' for this problem
    though it doesn't address the goal of code sharing at all
is to have classes Instructor,  AsstProf, and  Professor
each of which possesses the necessary data and operations
c_tchrs/c_tchrs_dup.java
Instructor          AsstProf            Professor       
+----------------+  +----------------+  +----------------+  
|age             |  |age             |  |age             |  
|get_age()       |  |get_age()       |  |get_age()       |  
|stress()        |  |stress()        |  |stress()        |  
|receive_email() |  |receive_email() |  |receive_email() |  
|etc.            |  |etc.            |  |etc.            |  
+----------------+  +----------------+  +----------------+  
(
incidentally this code demonstrates putting multiple classes together in one file
because they're all so 
in this situation, Java compels only one class can be  public
otherwise programmers too  to keep track of multiple files could be grouping classes when it makes no sense
    e.g.  class String  with  class Rectangle
Java coerces 
)
blatant repetition, eh?


another basic approach to this problem is to have a class 
possessing the common data and operations
and classes Instructor,  AsstProf, and  Professor
each of which  a  CollegeTeacher  object
and uses its data and methods:
c_tchrs/c_tchrs_compos.java
Instructor          AsstProf            Professor       
+----------------+  +----------------+  +----------------+  
|CollegeTeacher  |  |CollegeTeacher  |  |CollegeTeacher  |  
|+-------------+ |  |+-------------+ |  |+-------------+ |  
||             | |  ||             | |  ||             | |  
||             | |  ||             | |  ||             | |  
|+-------------+ |  |+-------------+ |  |+-------------+ |  
|                |  |                |  |                |  
+----------------+  +----------------+  +----------------+  
deficiencies of this  a.k.a. containment:
- explicit 'chaining' invocations needed for containing classes to use common attributes held by class CollegeTeacher
- some code such as that chaining repeated
though seeking to avoid repetition


avoids those deficiencies:

c_tchrs/c_tchrs_inherit.java
don't write  increment_ecc()  in  class Professor  because
inherit it from  class CollegeTeacher
and then inside  cope()  inside  class Professor,
invocation of  increment_ecc()  uses this inherited method

but respect for  Professor  spec. differently than basic
so  Professor  should have its own method respect()
so  what would have been the inherited method:
simply write own method with same name, arguments

but then rem. if it's desired for the subclass to have its own overriding method but also sometimes invoke the super-class's method,
use "super.method(args)"
e.g.    inside sub-class's  receive_email()

and then constructors like that but more special: 


further have polymorphism:

can store objects of sub-class in variables of super-class
e.g.:
CollegeTeacher c_tchr = p_a;
(actual code uses  ia[0]  etc. like  c_tchr  here)
c_tchr = ap_b;

but considering that a variable can thus hold an object of different classes at different times,
for any method-invocation    object_variable . method(arguments)
does system invoke method
specified for the object_variable's class
or for class of actual object stored in object_variable?
e.g. does    ia[i].receive_email()  invoke only  CollegeTeacher.receive_email()
even if variable  ia[i]  contains an object of class AsstProf ?

execution depends on class of actual object stored in object_variable
  "dynamic" because determination of which method to execute is determined while the program is running
versus being done more 'statically' before execution by compiler simply checking type of variable  ia[i] -- which does have its own method receive_email()  that could be invoked




summary of this lecture-module

basics of extending classes a.k.a. inheriting among classes:


(Copyright © 2009 by Hugh McGuire   — for thoughts about this, see   http://www.cis.gvsu.edu/~mcguire/teaching/copyright_thoughts.html .)