SDSU CS535 Object-Oriented Programming & Design
Fall Semester, 1996
Inheritance

[To Lecture Notes Index]
San Diego State University -- This page last updated Sep 24, 1996
----------

Contents of Inheritance

    1. References
    2. Inheritance
      1. Super
      2. This Again
      3. Static Methods
      4. Access Levels and Inheritance
      5. Inheritance and Final
      6. Constructors and Inheritance
      7. Class Object
      8. Abstract Classes
      9. Interfaces

Inheritance Slide # 1

References


Core Java, Chapter 4

The Java Programming Language, Arnold and Gosling, 1996, Chapters 3 and 4

The Java Language Specification, Gosling, Joy, Steele, 1996, section 6.6

java.lang.Object source code, rohan:/opt/java/src/java/lang/Object.java
Inheritance Slide # 2Listen Here!

Inheritance

class  Parent  {

   public int  parentVariable = 10;

   public  void  parentFunction()  {
      System.out.println(  "Parent Function"  );
   }

}

class  Child  extends  Parent  {

   public  void  childFunction()  {
      parentFunction();
      System.out.println(  "In Child " + parentVariable  );
   }
}

class  Inheritance  {

   public static void main( String args[] ) {
   
      Child  example  =  new Child();
      example.childFunction();
      example.parentFunction();
      System.out.println( example.parentVariable );
   }
}
Output
Parent Function
In Child 10
Parent Function
10
Inheritance Slide # 3Listen Here!
Hiding Fields
class  Parent  {
   public String  name  =  "Parent";
   public int test;
   public  void  parentPrint() {
      System.out.println(  name  );
   }
}

class  Child  extends  Parent  {
   public String  name  =  "Child";
   public String test;

   public  void  print()  {
      System.out.println(  name  );
   }
}

class  HiddenFields  {

   public static void main( String args[] ) {

      Child  whoAmI  =  new Child();

      whoAmI.print();
      whoAmI.parentPrint();

      System.out.println( whoAmI.name );
      System.out.println( ( (Parent ) whoAmI).name );
   }
}
Output
Child
Parent
Child
Parent
Inheritance Slide # 4Listen Here!
Overriding Methods
class  Parent  {
   
   public void print() {
      System.out.println( "In Parent" );
   }
}

class  Child  extends  Parent  {

   public  void  print()  {
      System.out.println( "In Child" );
   }
   
}

class  OverriddingMethods  {
   public static void main( String args[] ) {

      Child  whoAmI  =  new Child();
      whoAmI.print();
      ( ( Parent ) whoAmI).print();
   }
}
Output
In Child
In Child
Inheritance Slide # 5Listen Here!
Terms and Rules

Overloading
Providing more than one method with the same name, but with different signatures

Overriding
A class replacing an ancestor's implementation of a method with an implementation of it own
Signature and return type must be the same
Static methods can not be overridden

Hiding Fields
Giving a field in a class the same name as a field in an ancestor hides the ancestor's field
The field exists, but can not be accessed by its simple name
When invoking a method on an object, the actual type of the object is used to determine which method implementation to use, that is the method is determined dynamically

When accessing a field in an object, the declared type of the reference is used to determine which field to use, that is the field is determined statically
Inheritance Slide # 6Listen Here!
Method vs. Field Access
class  Parent  {
   public String  name  =  "Parent";

   public  void  print() {
      System.out.println( "In Parent \t" + name  );
   }
}

class  Child  extends  Parent  {
   public int  name  =  5;

   public  void  print()  {
      System.out.println( "In Child \t" + name  );
   }
}

class  StaticVersesDynamic  {

   public static void main( String args[] ) {

      Child  prodigy  =  new Child();
      prodigy.print();   //Prints   In Child    5
      Console.println( prodigy.name );   //Prints    5

      Parent confused = new Child();
      confused.print();   //Prints   In Child    5
      Console.println( confused.name );   //Prints    Parent

      Parent ok = new Parent();
      ok.print();   //Prints   In Parent    Parent
      Console.println( ok.name );   //Prints    Parent
   }
}

Inheritance Slide # 7Listen Here!
Fancy Accesses
class  Parent  {
   
   private String name = "Parent";
   
   public void print() {
      System.out.println( "In Parent" );    
   }
   
   public void whichGetsCalled() {
      System.out.println( "In whichGetsCalled " + name );
      print();
   }
}

class  Child  extends  Parent  {

   private String name = "Child";
   
   public  void  print()  {
      System.out.println( "In Child" );
   }
}

class  Polymorphism  {
   public static void main( String args[] ) {

      Parent  whoAmI  =  new Child();
      whoAmI.whichGetsCalled();
      whoAmI = new Parent();
      whoAmI.whichGetsCalled();
   }
}
Output
In whichGetsCalled Parent
In Child
In whichGetsCalled Parent
In Parent
Inheritance Slide # 8
Overloading, Overriding and Return Types
class  Parent  {
   
   public void print() {
      System.out.println( "In Parent" );
   }
   
   public void print( String message ) {
      System.out.println( "In Parent" + '\t' + message );
   }

   public void print( int value ) {
      System.out.println( "In Parent" + '\t' + value );
   }
}

class  Child  extends  Parent  {

   public  int  print()  {            // Compiler Error
      System.out.println( "In Child" );
      return 5;
   }

   public void print( String message ) {
      System.out.println( "In Child" + '\t' + message );
   }
}

class  ReturnTypesCount  {
   public static void main( String args[] ) {

      Child  whoAmI  =  new Child();
      whoAmI.print();
      whoAmI.print( "Hi Mom" );
      whoAmI.print( 10 );         // Ok in Java, 
                              // Compile error in C++
   }
}

Inheritance Slide # 9Listen Here!

Super


super
Refers to the superclass of class that implements the method containing the reference to super
All references to super are resolved statically
class  Parent  {
   String  name  =  "Parent";    
   }

class  Child  extends  Parent  {
   String  name  =  "Child";

   public  void  print()  {
      System.out.println(  name  );
      System.out.println(  super.name  );
      System.out.println(  Parent.name  );
   }
}

class  SuperMain  {
   public static void main( String args[] ) {

      Child  whoAmI  =  new Child();
      whoAmI.print();
   }
}
Output
Child
Parent
Parent
Inheritance Slide # 10Listen Here!
More Super
class  Parent  {
   
   public String name = "Parent";
   
   public void print() {  System.out.println( "In Parent" );    }
}

class  Child  extends  Parent  {

   public String name = "Child";
   
   public  void  print()  {
      System.out.println( "In Child" );    
   }
   
   public  void superTest() {
      System.out.println( "In Child test " + super.name );
      super.print(); 
   }      
}

class GrandChild extends Child {

   public String name = "Child";

   public  void  print()  {
      System.out.println( "In GrandChild" );    
   }
}
      
class  SuperIsStatic  {
   public static void main( String args[] ) {

      GrandChild  whoAmI  =  new GrandChild();
      whoAmI.superTest();
   }
}
Output
In Child test Parent
In Parent
Inheritance Slide # 11Listen Here!

This Again


this
references to fields via this are resolved statically
references to methods via this are resolved dynamically
class  Parent  {
   String  name  =  "Parent";

   public  void  print()  {System.out.println( "In Parent" + name ); }

   public  void  thisFunction()  {
      System.out.println(  this.name  );
      this.print();
   }
}

class  Child  extends  Parent  {
   String  name  =  "Child";

   public  void  print() { System.out.println( "In Child " + name ); }
}

class  This  {
   public static void main( String args[] )   {
      Parent  parentThis  =  new Child();
      parentThis.thisFunction();

      Child  childThis  =  new Child();
      childThis.thisFunction();
   }
}
Output
Parent
In Child Child
Parent
In Child Child
Inheritance Slide # 12Listen Here!

Static Methods


Static methods reference are resolved statically
class  Parent  {

   public  static  void  classFunction()  {
      System.out.println(  "In Parent"  );
   }

   public  static  void  inheritMe()  {
      System.out.println(  "Inherited"  );
   }
}

class  Child  extends  Parent  {

   public  static  void  classFunction()  {
      System.out.println(  "In Child"  );
   }
}

class  StaticTest  {

   public static void main( String args[] ) {

      Parent  exam  =  new Child();
      exam.classFunction();

      Child  question  =  new Child();
      question.classFunction();
      question.inheritMe();
   }
}
Output
In Parent
In Child
Inherited
Inheritance Slide # 13Listen Here!

Access Levels and Inheritance


Private class members are accessible only in the class they are defined
class Private {
   private String name = "Private";

   public void print() {
      System.out.println( name );
   }

   public void tricky( Private argument ) {
      argument.name = "This access is legal";
   }
}

class Excluded extends Private {

   public void cantPrint() {
      System.out.println( name );    // Compile error
   }
}

class PrivateExample {
   public static void main( String[] args ) {

      Private top = new Private();
      Private bottom = new Private();
      top.tricky( bottom );
      bottom.print();
   }
}
Output (if compile error is removed )
This access is legal
Inheritance Slide # 14Listen Here!
Protected Access and Inheritance
protected
Accessible in the package that contains the class
Accessible in all subclasses
package Botany;

public class Protected {
   protected String name = "Protected";
}

package Botany;

public class NoRelation {
   public  void  SampleAccess( Protected accessOK )  {
      accessOK.name  =  "This is legal";
   }
}

package  Tree;

public class NoRelationEither {
   public  void  SampleAccess( Botany.Protected noAccess)  {
      noAccess.name  =  "This is a compile Error";
   }
}

package  Tree;

public class Child  extends  Botany.Protected {
   public  void  SampleAccess( Botany.Protected noAccess,
                           Child  accessOK)  {
      name = "This is legal, I am related";
      noAccess.name  =  "This is a compile Error";
      accessOK.name  =  "This is legal";
   }
}

Inheritance Slide # 15
Protected Access and Inheritance: The Rules[1]

Let C be a class with a protected member or constructor.

Let S be a subclass of C in a different package.

The declaration of the use of the protected member or constructor occurs in S.

If the access is of a protected member, let Id be its name
If the access is by a field access expression of the form super.ID, then the access is permitted
If the access is by a qualified name Q.Id, where Q is a type name, then the access is permitted if and only if Q is S or a subclass of S.
If the access is by a qualified name Q.Id, where Q is an expression then the access is permitted if and only if the type of the expression Q is S or a subclass of S
If the access is by a field access expression E.Id, then the access is permitted if and only if the type of E is S or a subclass of S

Inheritance Slide # 16Listen Here!
No Explicit Access and Inheritance
No Explicit Access
Accessible in the package that contains the class
Not accessible outside the package that contains the class
package Botany;

public class NoExplicit {
   String name = "No explicit access level given";
}

package Botany;

public class NoRelation {
   public  void  SampleAccess( NoExplicit accessOK )  {
      accessOK.name  =  "This is legal";
   }
}

package  Tree;

public class NoRelationEither {
   public  void  SampleAccess( Botany.NoExplicit noAccess)  {
      noAccess.name  =  "This is a compile Error";
   }
}

package  Tree;

public class Child  extends  Botany.NoExplicit {
   public  void  SampleAccess( Botany.NoExplicit noAccess,
                           Child  alsoNoAccess)  {
      name = "I am related, but this is NOT LEGAL";
      noAccess.name  =  "This is a compile Error";
      alsoNoAccess.name  =  "This is a compile Error";
   }
}

Inheritance Slide # 17Listen Here!

Inheritance and Final


The final modifier provides:
Security
Performance optimizations
A class declared to be final, can not have any subclasses

final  class  EndOfTheLine  {

   int  noSubclassPossible;

   public  void  aFunction()  {
      System.out.println(  "Hi Mom"  );
   }
}
class  ThisWillNotWork  extends  EndOfTheLine   {
   int  ohNo;
}

Does not compile

Inheritance Slide # 18Listen Here!
Final Method

A final method can not be overwritten
class  Parent  {

   public  final  void  theEnd()  {
      System.out.println(  "This is it"  );
   }

   public  void  normal()  {
      System.out.println(  "In parent"  );
   }
}

class  Child  extends  Parent  {

   public  void  theEnd()     {         // Compile Error
      System.out.println(  "Two Ends?"  );
   }

   public  void  normal()  {
      System.out.println(  "In Child"  );
   }
}

Inheritance Slide # 19Listen Here!

Constructors and Inheritance

class  Parent  {

   public  Parent()  {
      System.out.println(  "In Parent"  );
   }
}

class  Child  extends  Parent  {

   public  Child()  {
      System.out.println(  "In Child"  );
   }

   public Child( String notUsed ) {
      System.out.println(  "In Child with argument"  );
   }
}

class  Constructors  {

   public static void main( String args[] ) {
      System.out.println(  "Construct Parent"  );
      Parent  sleepy   =  new Parent();

      System.out.println(  "Construct Child"  );
      Child  care  =  new Child();
      care  =  new Child( "Try Me" );
   }
}
Output
Construct Parent
In Parent
Construct Child
In Parent
In Child
In Parent
In Child with argument

Inheritance Slide # 20Listen Here!
Calling Other Constructors
class  Parent  {

   public  Parent(  )  {
      System.out.println(  "In Parent, No Argument"  );
   }

   public  Parent(  String  message  )  {
      System.out.println(  "In Parent"  +  message  );
   }
}

class  Child  extends  Parent  {

   public  Child( String  message,  int  value  )  {
      this(  message  );                      // if occurs must be first
      System.out.println(  "In Child"  );
   }

   public  Child( String  message  )  {
      super(  message  );      // if occurs must be first
      System.out.println(  "In Child"  +  message  );
   }
}

class  Constructors  {
   public static void main( String args[] ) {
      System.out.println(  "Construct Child"  );
      Child  care  =  new Child( ">Start from Child<", 5 );
   }
}
Output
Construct Child
In Parent>Start from Child<
In Child>Start from Child<
In Child
Inheritance Slide # 21Listen Here!

Class Object


All classes inherit from Object
class Parent {
int size;
}

Is short hand for
class Parent extends Object {
int size;
}
class  Parent  {
   int  size;
}

class  TestObject  {

   public static void main( String args[] ) {

      Parent  watchThis  =  new Parent();

      int  myHash  =  watchThis.hashCode();  

      System.out.println(  myHash  );

         // Where does hashCode come from?
   }
}

Inheritance Slide # 22Listen Here!
Object's Methods (minus thread related)

clone()
Creates a clone of the object.

equals(Object)
Compares two Objects for equality.
Uses "==" to test for equality

finalize()
Code to perform when this object is garbage collected.

getClass()
Returns the Class of this Object.

hashCode()
Returns a hashcode for this Object.

toString()
Returns a String that represents the value of this Object.

If a class needs a implementation of equals which differs from the default "equals" the class should override both equals and hashCode

If two different objects satisfy the equals method, the hashCode should return the same value for both objects
Inheritance Slide # 23Listen Here!
Dangerous and Advanced Material
import sdsu.io.Console;

class Foobar {
   public String name = "Skip if this confuses you";
}

class DealingWithClasses {
   public static void main( String[] arguments ) throws 
         ClassNotFoundException, IllegalAccessException, 
         InstantiationException {

      Foobar  example = new Foobar();

      Console.println( example.getClass().getName() );
      Console.println( example.getClass().getSuperclass() );

      // Stop reading while it is still safe
      // Creating  an object from a string
      example = (Foobar) Class.forName( "Foobar" ).newInstance();

      String  whichClass = "java.util.Vector";

      Object interesting = Class.forName( whichClass ).newInstance();
      Console.println( interesting.getClass().getName() );
      
      whichClass = Console.readLine( "Enter a class name" );
      interesting = Class.forName( whichClass  ).newInstance();
      Console.println( interesting.getClass().getName() );
   }
}


Inheritance Slide # 24Listen Here!
Casting and Classes
class  Parent  {  int  data;  }

class  Child  extends  Parent  {  String  name;  }

class  Uncle  {  String  rich;  }

class  Casting {

   public static void main( String args[] )  {
      Object  object;
      Parent  parent;
      Child  child  =  new Child();
      Uncle  uncle;

      parent  =  child;
      object  =  child;
      parent  =  (Parent)  object;
      child  =  (Child)  object;

      uncle  =  (Uncle)  object;   //Runtime exception
      }
}
Output
java.lang.ClassCastException: Child
at Casting.main(All.java:21)

Inheritance Slide # 25Listen Here!

Abstract Classes

abstract  class  NoObjects  {

   int  noDirectObjectPossible  =  5;

   public  void  aFunction()  {
      System.out.println(  "Hi Mom"  );
   }

   public  abstract  void  subClassMustImplement(  int  foo  );
}

class Concrete  extends  NoObjects  {

   public  void  subClassMustImplement(  int  foo  )  {
      System.out.println(  "In Concrete"  );
   }
}

class  AbstractClasses  {

   public static void main( String args[] ) {
      NoObjects  useful  =  new  Concrete();
      Concrete  thisWorks  =  new  Concrete();

      useful.subClassMustImplement( 10 );
      System.out.println(  thisWorks.noDirectObjectPossible  );
   }
}
Output
In Concrete
5
Inheritance Slide # 26Listen Here!

Interfaces


"Conducting" is when you draw "designs" in the nowhere - with your stick, or with your hands - which are interpreted as "instructional messages" by guys wearing bow ties who wish they were fishing.
Frank Zappa


The public methods of classes can be thought of as units of design

Classes combine design and implementation

Interfaces can specify public methods but can have no implementation of methods

Interfaces can have variables, but they are static and final

Interfaces give a type of multiple inheritance

Inheritance Slide # 27Listen Here!
Interface Example

In file Flyer.java:
public  interface  Flyer  {
      public  boolean  hasWings();
}


In file test.java:
interface  Mammal  {

   static  boolean  hasLungs  =  true;
   public  boolean  hasLegs();
}

interface  Noisy  extends  Mammal  {

   public  boolean  hasBark();
}

class  Dog  implements  Noisy  {

   public  boolean  hasLegs() {
      return true;
   }

   public  boolean  hasBark()  {
      return true;
   }
}

Inheritance Slide # 28Listen Here!
// file test.java continued

class  Bird  implements  Mammal,  Flyer  {

   public  boolean  hasLegs(){
      return true;
   }

   public  boolean  hasWings()  {
      return true;
   }
}

class  InterfaceExample  {

   public static void main( String args[] )   {

      Bird  robin  =  new  Bird();
      Flyer  crow  =  new  Bird();
      Noisy  fido  =  new  Dog();
      Mammal  fifi  =  new  Noisy();      //Compiler Error

      robin.hasLegs();
      robin.hasWings();
      boolean test  =  robin.hasLungs;
      crow.hasLegs();      //Compile Error
   }
}

Inheritance Slide # 29Listen Here!
Interfaces and Name Conflicts
public interface Left {   public void truth();  }

public interface Right {   public boolean truth(); }

class Congress implements Left, Right {
   public ????  truth() {   }
}

Method Name Conflicts

If a class implements two interfaces that each have a method with the same name, say foo, then
if both foo' s have different signatures, then the class implements two overloaded foo methods
if both foo' s have the same signature and same return type, then the class implements only the one foo
if both foo' s have the same signature and different return types, then the class can not implement both interfaces
if both foo' s have the same signature, same return type but differ in the types of exceptions they throw, then the class implements only the one foo, but it must contain the exceptions both foo's
If a class implements two interfaces that each have a field with the same name, say bar, then the class has to use the full names for the fields.

----------