SDSU CS 596 Java Programming
Fall Semester, 1998
Inheritance
To Lecture Notes Index
© 1998, All Rights Reserved, SDSU & Roger Whitney
San Diego State University -- This page last updated 05-Oct-98

Contents of Doc 7, Inheritance


References



The Java Programming Language ,2nd Ed. Arnold and Gosling, 1998, Chapter 3

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


Listen Here!S-sept21 7mins, Q-sept24 4mins Doc 7, Inheritance Slide # 2

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

Doc 7, Inheritance Slide # 3
Inheritance

A class can be extended or subclassed

The class that is extended is a superclass

Some people use the words parent class or base class to mean a superclass

The extended class is a subclass or extended class of its superclass

Some people use the word child class to mean subclass

An object created from the subclass has its own copy of all the nonstatic fields defined in its superclass

Each class defines a type. We can declare variables & fields of the new type

A subclass defines a subtype of its parent class.

Java does not support multiple inheritance

Listen Here!S-sept21 1min, Q-sept24 3mins Doc 7, Inheritance Slide # 4

Class Object


All classes inherit directly or indirectly from java.lang.Object

class Parent { int size; }

Is short hand for

class Parent extends Object { int size; }

The child class below is a grandchild of Object

Having a common ancestor class allows java to provide standards on all objects, like toString()

class  Parent  { int  size; }
class Child extends Parent { int age; }
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?
   }
}

Listen Here!S-sept21 3mins Doc 7, Inheritance Slide # 5
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 an 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

Listen Here!S-sept21 26mins, Q-sept24 15mins Doc 7, Inheritance Slide # 6
Casting and Classes
An instance of a child class can be assigned to a variable (field) of the parent class. If a variable references an object of a subclass, the object can be cast down to its actual type with an explicit cast. The explicit cast is required. A runtime error occurs when explicitly casting an object to a type that it is not. In the code below the cast "(Uncle) object" is a runtime error because at that time object holds an instance of the Child class, which is not of type (or subclass) of Uncle. An object of type Parent cannot be cast to type Child.

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;   // explicit cast down
      child  =  (Child)  object;      // explicit cast down
      uncle  =  (Uncle)  object;   //Runtime exception
      }
}
Output
java.lang.ClassCastException: Child: cannot cast to Uncle

Doc 7, Inheritance Slide # 7

Inheritance and Name Clashes


What happens when the parent class has a method(field) with the same name as a method(field) of the child class?

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 short name
When invoking a method on an object, the actual type of the object is used to determine which method implementation to use. Method references are determined dynamically. You determine which method will be used at runtime by examining the actual object you are sending the method to.

When accessing a field in an object, the declared type of the reference is used to determine which field to use. Field references are determined statically. You determine which field will be used by looking at the source code.

Listen Here!S-sept23 9mins, Q-sept24 4mins Doc 7, Inheritance Slide # 8
Hiding Fields
A parent and child class can both have non-static fields with the same name. An instance of the child class will always contain both fields, even if access levels on the parent field do not allow the child to access the parent's field directly. Determine which "name" will be used statically.

class  Parent  {
   public String  name  =  "Parent";
   public  void  parentPrint() { System.out.println(  name  ); }
}
class  Child  extends  Parent  {
   String  name  =  "Child";
   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

Listen Here!S-sept23 8mins, Q-sept24 3mins Doc 7, Inheritance Slide # 9
Overriding Methods
Note that the statement "overRidden.print();" prints out different text depending on what type of object overRidden references.

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 overRidden = whoAmI;
      overRidden.print();
      overRidden = new Parent();
      overRidden.print();
   }
}

Output
In Child
In Child
In Parent


Listen Here!Q-sept24 4mins Doc 7, Inheritance Slide # 10
Why not the same rule for Methods and Fields?

Resolving hidden fields dynamically would allow child classes to break parent method that refer to parent fields. Assume that hidden fields are found dynamically. Let a child class create a field of the same name, but different type as parent's field. Calling a parent's method that uses the field through a child's instance would break the method. The field used would now be the wrong type. If fields were resolved dynamically, then in the statement " trouble.test();" the test method would try to divide a string by 3, which is not allowed in Java.

class  Parent  {
   public  int  name  =  5;
   public  void  test() {
      System.out.println( "In Parent \t" + (name / 3) );
   }
}
class  Child  extends  Parent  {
   public String name  =  "Can't divide me";
}

class FieldsMustBeResolveStaticly {
   public static void main( String args[] ) {
      Child  trouble  =  new Child();
      trouble.test();
   }
}

Listen Here!S-sept23 9mins Doc 7, Inheritance Slide # 11
Fancy Accesses
Since method access is determined dynamically, methods that methods call are also determined dynamically. Since Child overrides the "print" method, which "print" is called in "whichGetsCalled" is also determined dynamically.
class  Parent  {
   private String name = "Parent";
   
   public void print() {
      System.out.println( "\t 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( "\t 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

Listen Here!S-sept23 2mins, Q-sept24 53secs Doc 7, Inheritance Slide # 12
This Again

this
references to fields via this are resolved statically
references to methods via this are resolved dynamically

That is to say, "this" follows the normal rules.

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

Listen Here!S-sept23 4mins Doc 7, Inheritance Slide # 13
Overloading, Overriding and Return Types
When overriding a method, the child's method must have the same signature and return type as the parent's method. In C++ if the parent class overloads a method name (i.e. print) and the child class overrides one of these methods, then the child can not directly access any of the overloaded parent's methods.
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++
   }
}

Listen Here!S-sept23 7mins, Q-sept24 5mins Doc 7, Inheritance Slide # 14

Super


super
Refers to the superclass of class that implements the method containing the reference to super
All references to super are resolved statically

To find out what class super refers to go to the source code, find the code that contains "super", then go to that classes parent class.

class  Parent  {   String  name  =  "Parent";     }
class  Child  extends  Parent  {
   String  name  =  "Child";
   public  void  print()  {
      System.out.println(  name  );
      System.out.println(  super.name  );
   }
}
class GrandChild extend Child {
   String name = "GrandChild";
}
class  SuperMain  {
   public static void main( String args[] ) {
      GrandChild whoAmI  =  new GrandChild();
      whoAmI.print();
   }
}
Output
Child
Parent

Listen Here!S-sept23 21secs Doc 7, Inheritance Slide # 15
super.super

Java does not allow you to chain supers to refer to your grandparent class

super.super is not allowed in Java

The need to reference a grandparent's class should be very rare

Listen Here!S-sept23 3mins Doc 7, Inheritance Slide # 16

Constructors and Inheritance


Before the constructor in a Child class is called, its parent's constructor will be called

If the Child class constructor does not do this, the parent's constructor with no arguments will be implicitly called

super( arg list) as the first line in a constructor explicitly calls the parent's constructor with the given signature

If
parent class implements a constructor with arguments &
parent class does not implement a constructor with no arguments

Then the Child constructors must eventually explicitly call a parents constructor


Listen Here!S-sept23 40secs, Q-sept24 6mins Doc 7, Inheritance Slide # 17
Implicit Call to Parent's Constructor

class  Parent  {
   public  Parent()  {
      System.out.println(  "\t In Parent"  );
   }
}
class  Child  extends  Parent  {
   public  Child()  {
      System.out.println(  "\t In Child"  );
   }
   public Child( String notUsed ) {
      System.out.println(  "\t 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();
      System.out.println(  "Construct Second Child"  );
      care  =  new Child( "Try Me" );
   }
}
Output
Construct Parent
   In Parent
Construct Child
   In Parent
   In Child
Construct Second Child
   In Parent
   In Child with argument

Listen Here!S-sept23 3mins, Q-sept24 5mins Doc 7, Inheritance Slide # 18
Explicit Call to Parent's 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

Listen Here!S-sept23 2mins Doc 7, Inheritance Slide # 19
No Default Parent Constructor

The compiler will not generate the default constructor for the class "Parent", since "Parent" has a constructor. The class "Child" makes an implicit call to the default constructor in "Parent". This causes a compile error.

class  Parent  {
   public  Parent(  String  message  )  {
      System.out.println(  "In Parent"  +  message  );
   }
}
class  Child  extends  Parent  {
   public  Child(   )  {            // Compile Error
      System.out.println(  "In Child"  );
   }
   public  Child( String  message  )  {
      super(  message  );      
      System.out.println(  "In Child"  +  message  );
   }
}


Doc 7, Inheritance Slide # 20
Nonstatic Methods in Constructors are Resolved Dynamically

Methods called in constructors follow the rules.

class Parent
   {
   public Parent( )
      {
      whichOne( );
      }
   
   public void whichOne( )
      {
      System.out.println( "In Parent" );
      }
   }
class Child extends Parent
   {
   public void whichOne( )
      {
      System.out.println( "In Child" );
      }
   }
class Test
   {
   public  static  void  main( String  args[] ) 
      {
      new Child( );
      }
   }
Output
In Child

Listen Here!Q-sept24 1min, S-sept28 4mins Doc 7, Inheritance Slide # 21

Static Methods


Static methods references 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

Listen Here!Q-sept24 2mins Doc 7, Inheritance Slide # 22

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

Listen Here!Q-sept24 5mins, S-sept28 6mins Doc 7, Inheritance Slide # 23
Private and Dynamic Method Binding

Since a private method can not be called from the child, when an inherited method (foo) calls the parent private method (Parent.bar), the parent private method is always the one called

class Madre {
   public void foo() { 
      bar(); 
   }
   private void bar()    { 
      System.out.println( "Madre bar"); 
   }
}
class Hija extends Madre {
   public void bar()  { 
      System.out.println( "Hija bar");
   }
   public static void main( String[] args ) {
      Hija confundido = new Hija ();
      confundido.foo();
   }
}
Output
Madre bar

Listen Here!Q-sept24 8mins, S-sept28 8mins Doc 7, Inheritance Slide # 24
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";
   }
}

Listen Here!S-sept28 50secs Doc 7, Inheritance Slide # 25
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

Listen Here!S-sept28 1min Doc 7, Inheritance Slide # 26
Package Access and Inheritance
Package 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";
   }
}

Listen Here!Q-sept24 5mins, S-sept28 2mins Doc 7, Inheritance Slide # 27
Inheritance of Access Levels

The access modifier of an overriding method must provide at least as much access as the overridden method

Note

A private method is not accessible to subclasses, so can not be overridden in the technical sense.

Thus, a subclass can declare a method with the same signature as a private method in one of its superclasses. There is no requirement that the return type or throws clause of the method bear any relationship to those of the private method in the superclass

class Parent
   {
   protected void foo()  {};
   public void bar() {};
   private void noSeeMe() {};
   }
class Child extends Parent
   {
   public void foo() {};         // OK
   protected void bar() {};      // Compile Error
   public int noSeeMe() { return 5;};   //OK
   }

Listen Here!Q-sept24 2mins, S-sept28 57secs Doc 7, Inheritance Slide # 28
Rules Are Different for Fields

Since fields are hidden, not overridden we can set the access permission on fields in the class "Child" independent of the access permissions of the fields in class "Parent"

class Parent
   {
   protected int foo;
   public int bar;
   }
class Child extends Parent
   {
   public int foo;         // OK
   protected int bar;      // OK
   }

Listen Here!Q-sept24 2mins, S-sept28 1min Doc 7, Inheritance Slide # 29

Inheritance and Final


The final modifier provides:

Security
Performance optimizations
A class declared 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


Listen Here!Q-sept24 2mins, S-sept28 54secs Doc 7, Inheritance Slide # 30
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"  );
   }
}


Listen Here!S-sept28 5mins, Q-oct1 4mins Doc 7, Inheritance Slide # 31

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

Listen Here!S-sept28 6mins Doc 7, Inheritance Slide # 32

Relationships between Classes


Is-kind-of or is-a
is-analogous-to
is-part-of or has-a

Is-kind-of, is-a, is-a-type-of

Let A and B be classes

To determine if A should be the parent class of B ask:

Is B an A ( or is B a type of A, or is B a kind of A)

If the answer is no, then do not make A the parent of B

If the answer is yes, then consider making A the parent of B

Example 1 Bank Accounts

A JuniorSavingsAccount is a type of a SavingsAccount

So, consider making JuniorSavingsAccount a subclass of SavingsAccount


Listen Here!S-sept28 3mins Doc 7, Inheritance Slide # 33

Is-kind-of, is-a, is-a-type-of


Example 2 Employees

Consider Employee, Manager, Engineer, and FileClerk

A Manager is a kind of an Employee

So should we make Employee a parent class of a Manager class?

Is Manager a class or a role that an Employee object will play?

Does Manager contain data or operations that Employee does not?
If no, then Manager is likely a role for an Employee object

A very common mistake is to use inheritance to model roles that an object of one class will take on in a program. Just because an employee object will take on the role of an engineer, does not mean we need an engineer class. What happens when Smith changes positions from an engineer to a manager?

class Employee { //lots of stuff here not shown }
class Driver
   {
   public static void main( String[] args )
      {
      Employee manager = new Employee( "Sally" );
      Employee engineer = new Employee( "Smith" );
      }
   }

Listen Here!S-sept28 1min Doc 7, Inheritance Slide # 34
Example 2 Employees - Continued

If Manager, etc are classes then several options:

Option 1 Direct inheritance


class Employee 
   {
   // stuff not shown
   }
class Manager extends Employee
   {
   // stuff not shown
   }

etc.

This option is not very flexible. What happens when an employee changes from one type of position to another? See Option 2

Listen Here!S-sept28 2mins Doc 7, Inheritance Slide # 35
Option 2 Separate Inheritance Structure


class Employee 
   {
   Role position;
   // stuff not shown
   }
class Role
   {
   // stuff not shown
   }
class Manager extends Role
   {
   // stuff not shown
   }

This is a much more flexible approach. It is very easy for an employee object to change roles. Compare this to option 1.

Listen Here!S-sept28 2mins Doc 7, Inheritance Slide # 36

is-analogous-to


If class X is-analogous-to class Y then look for superclass



Example BankAccounts

A checking account is analogous to a saving account



Listen Here!S-sept28 2mins Doc 7, Inheritance Slide # 37

is-part-of or has-a


If class A is-part-of class B then there is no inheritance

Some negotiation between A and B for responsibilities may be needed

Example: Linked-List class and a Stack

A stack uses a linked-list in its implementation

A stack has a linked-list

The Stack class and the LinkedList class are separate classes


class LinkedList
   {
   public void addFront( Object item) { // not shown}
   public Object removeFront() { // not shown}
   public Object removeEnd() { // not shown}
   }
class Stack
   {
   LinkedList   stackElements = new LinkedList();
   public void push( Object item )
      {
      stackElements.addFront( item);
      }
   }

Listen Here!S-sept28 5mins Doc 7, Inheritance Slide # 38
A Common Mistake

Using inheritance with a is-part-of (has-a) relation between classes

class LinkedList
   {
   // fields not shown
   public void addFront( Object item) { // not shown}
   public Object removeFront() { // not shown}
   public Object removeEnd() { // not shown}
   }
class Stack extends LinkedList
   {
   public void push( Object item )
      {
      addFront( item);
      }
   }

class Test
   {
   public static void main( String[] arguments)
      {
      Stack problem = new Stack();
      problem.push( "Hi");
      problem.push( "Mom" );
      problem.removeEnd();   // ????
      }
   }

Doc 7, Inheritance Slide # 39
[1]From The Java Language Specification, Gosling, Joy, Steele, 1996, section 6.6.2, page 100

Copyright © 1998 SDSU & Roger Whitney, 5500 Campanile Drive, San Diego, CA 92182-7700 USA.
All rights reserved.

visitors since 22-Sep-98