Inheritance Inheritance is the process of using features (both attributes and methods) from an existing class. The existing class is called the superclass and the new class, which inherits the superclass features, is called the subclass. superclass: Car subclasses: Truck, Limo & Racecar “Is-A” and “Has-A” The creation of new classes with the help of existing classes makes an important distinction between two approaches. An "is-a" relationship declares a new class as a special “new-and-improved” case of an existing class. In Geometry, a parallelogram "is-a" quadrilateral with special properties. A “has-a” relationship declares a new class composed of an existing class or classes. A line has points, a square has lines, and a cube has squares. A truck "is-a" vehicle, but it "has-an" engine. In computer science an "is-a" relationship involves inheritance and a "has-a" relationship involves composition. // Java0901.java // This program demonstrates fundamental inheritance with <extends>. There are no constructors yet, // which results in Java handling the construction and assigning default values to the attributes. public class Java0901 { public static void main(String args[]) { System.out.println("\nJAVA0901\n"); Student tom = new Student(); tom.showAge(); tom.showGrade(); System.out.println(); } } class Person { private int age; public void showAge() { System.out.println("Person's Age is unknown right now"); } } class Student extends Person { private int grade; public void showGrade() { System.out.println("Student's Grade is unknown right now"); } } // Java0902.java // This program adds constructors to the <Person> and <Student> classes. // Note how the <Person> constructor is called, even though there does not appear // to be a <Person> object instantiated. public class Java0902 { public static void main(String args[]) { System.out.println("\nJAVA0902\n"); Student tom = new Student(); tom.showData(); System.out.println(); } } class Person { private int age; public Person() { System.out.println("Person Constructor"); age = 17; } public int getAge() { return age; } } class Student extends Person { private int grade; public Student() { System.out.println("Student Constructor"); grade = 12; } public int getGrade() { return grade; } public void showData() { System.out.println("Age: " + getAge()); System.out.println("Grade: " + getGrade()); } } Inheritance and Constructors When an object of a subclass is instantiated, the constructor of the superclass is called first, followed by a call to the constructor of the subclass. // Java0903.java // This program shows that the subclass does not have access to the private data of the superclass. // This program will not compile. public class Java0903 { public static void main(String args[]) { System.out.println("\nJAVA0903\n"); Student tom = new Student(); tom.showData(); System.out.println(); } } class Person { private int age; public Person() { System.out.println("Person Constructor"); age = 17; } } class Student extends Person { private int grade; public Student() { System.out.println("Student Constructor"); public void showData() { System.out.println("Student's Grade is " + grade); System.out.println("Student's Age is " + age); } } grade = 12; } // Java0904.java // This program changes private member data to "protected" data. // The Student class can now access data from the Person class. public class Java0904 { public static void main(String args[]) { System.out.println("\nJAVA0904\n"); Student tom = new Student(); tom.showData(); System.out.println(); } } class Person { protected int age; public Person() { System.out.println("Person Constructor"); age = 17; } } class Student extends Person { private int grade; public Student() { System.out.println("Student Constructor"); public void showData() { System.out.println("Student's Grade is " + grade); System.out.println("Student's Age is " + age); } } grade = 12; } Public, Private, & Protected Attributes & methods declared public can be accessed by methods declared both outside and inside the class. Attributes & methods declared private can only be accessed by methods declared inside the class. Attributes & methods declared protected can only be accessed by methods declared inside the class or subclass, and yes it can also be accessed from anywhere in the same package. // Java0905.java // This program uses a parameter constructor to pass information to the Student constructor. // Person still calls a default (no parameter) constructor. public class Java0905 { public static void main(String args[]) { System.out.println("\nJAVA0905\n"); Student tom = new Student(12); tom.showData(); System.out.println(); } } class Person { protected int age; public Person() { System.out.println("Person Default Constructor"); age = 17; } public int getAge() { return age; } } class Student extends Person { protected int grade; public Student(int g) { System.out.println("Student Parameter Constructor"); grade = g; } public int getGrade() { return grade; } public void showData() { System.out.println("Student's Grade is " + grade); System.out.println("Student's Age is " + age); } } // Java0906.java This program demonstrates how to pass information to the superclass by using <super>. public class Java0906 { public static void main(String args[]) { System.out.println("\nJAVA0906\n"); Student tom = new Student(12,17); tom.showData(); } } class Person { protected int age; public Person(int a) { System.out.println("Person Parameter Constructor"); age = a; } public int getAge() { return age; } } class Student extends Person { protected int grade; public Student(int g, int a) { super(a); // this must be the first call grade = g; System.out.println("Student Parameter Constructor"); } public int getGrade() { return grade; } public void showData() { System.out.println("Student's Grade is " + getGrade()); System.out.println("Student's Age is " + getAge()); } } // Java0907.java // In this program both the <Person> class and the <Student> class each have a method with the same identifier. // The program returns the grade information twice and does not know that the <getData> method of the <Person> // class should also be used. public class Java0907 { public static void main(String args[]) { System.out.println("\nJAVA0907\n"); Student tom = new Student(12,17); tom.showData(); System.out.println(); } } class Person { protected int age; public Person(int a) { System.out.println("Person Parameter Constructor"); age = a; } public int getData() { return age; } } class Student extends Person { protected int grade; public Student(int g, int a) { super(a); grade = g; System.out.println("Student Parameter Constructor"); } public int getData() { return grade; } public void showData() { System.out.println("Student's Grade is " + getData()); System.out.println("Student's Age is " + getData()); } } // Java0908.java // This program solves the problem of Java0907.java. // The Java keyword <super> is used to indicate that the getData method of the superclass is intended. public class Java0908 { public static void main(String args[]) { System.out.println("\nJAVA0907\n"); Student tom = new Student(12,17); tom.showData(); System.out.println(); } } class Person { protected int age; public Person(int a) { System.out.println("Person Parameter Constructor"); age = a; } public int getData() { return age; } } class Student extends Person { protected int grade; public Student(int g, int a) { super(a); grade = g; System.out.println("Student Parameter Constructor"); } public int getData() { return grade; } public void showData() { System.out.println("Student's Grade is " + getData()); System.out.println("Student's Age is " + super.getData()); } } // Java0909.java // This program demonstrates inheritance at three levels. public class Java0909 { public static void main(String args[]) { System.out.println("\nJAVA0909\n"); Cat tiger = new Cat("Tiger",500,5); System.out.println(); System.out.println("Animal type: " + tiger.getType()); System.out.println("Animal weight: " + tiger.getWeight()); System.out.println("Animal age: " + tiger.getAge()); System.out.println(); } } class Animal { protected int age; class Mammal extends Animal { protected int weight; public Mammal(int w, int a) { System.out.println( "Mammal Constructor Called"); } public int getWeight() { return weight; } } class Cat extends Mammal { protected String type; public Cat(String t, int w, int a) { public Animal(int a) { } super(w,a); type = t; System.out.println( "Cat Constructor Called"); System.out.println("Animal Constructor Called"); age = a; } public int getAge() { return age; } super(a); weight = w; } public String getType() { return type; } } Using super The keyword super used as the first statement in a constructor passes information to the super class constructor, like super(a); The same keyword super used in front of a method indicates that a method of the superclass needs to be called, like super.getData(); Information can be passed up to multiple inheritance levels, but it can only be passed one level at one time. Multi-Level Inheritance & Multiple Inheritance The previous program showed an example of Multi-Level Inheritance. Multiple Inheritance is something different. It occurs when one subclass inherits from two or more superclasses. This feature is available in C++. It is NOT available in Java. Multi-Level Inheritance Animal Multiple Inheritance Reptile Extinct Mammal Dinosaur Dog Terrier Composition Composition occurs when the data attributes of one class are objects of another class. You do NOT say “A Car is-an Engine” but you DO say “A Car has-an Engine” class: Car Contained Classes: Engine Tire Can it be both? It is possible for a program to use both inheritance and composition. You can say “A TireSwing is-a Swing”. You can also say, “A TireSwing has-a Tire.” Note: The same Tire can be used for a Car and a Swing. superclass: Swing subclass: TireSwing Contained Class: Tire // Java0910.java // This program uses an <Engine> object in a "has-a" composition relationship. public class Java0910 { public static void main(String args[]) { System.out.println("\nJAVA0910\n"); Car car = new Car("Ford",350); System.out.println(); car.getData(); System.out.println(); } } class Car { private String type; private Engine engine; public Car(String t, int hp) { System.out.println("Car Constructor Called"); type = t; class Engine { private int horsePower; engine = new Engine(hp); public Engine(int hp) } { System.out.println( "Engine Constructor Called"); horsePower = hp; public void getData() { System.out.println("Car Type: " + type); System.out.println("Horse Power: " + engine.getHorsePower()); } } public int getHorsePower() { return horsePower; } } } // Java0911.java // This program uses multiple classes // not in an "is-a" inheritance relationship, // but a "has-a" composition relationship public class Java0911 { public static void main(String args[]) { System.out.println("\nJAVA0911\n"); Car car = new Car("Ford",6,350,"Red"); System.out.println(); car.getData(); System.out.println(); } } class Car { private String type; private Wheel wheel; private Engine engine; private Paint paint; wheel = new Wheel(wc); engine = new Engine(hp); paint = new Paint(pc); class Wheel { private int wheelCount; public Wheel(int wc) { System.out.println( "Wheel Constructor Called"); wheelCount = wc; } } public Engine(int hp) { System.out.println( "Engine Constructor Called"); horsePower = hp; } public Car(String t, int wc, int hp, String pc) { System.out.println( "Car Constructor Called"); type = t; } public int getWheelCount() { return wheelCount; } class Engine { private int horsePower; public void getData() { System.out.println("Car Type: " + type); System.out.println("Wheel Count: " + wheel.getWheelCount()); System.out.println("Horse Power: " + engine.getHorsePower()); System.out.println("Paint Color: " + paint.getPaintColor()); } } public int getHorsePower() { return horsePower; } } class Paint { private String paintColor; public Paint(String pc) { System.out.println( "Paint Constructor Called"); paintColor = pc; } public String getPaintColor() { return paintColor; } } Jack-O'-lantern Case Study We will now look at a simple 3-step Case Study that will ultimately draw a Jack-O’-lantern. The end result is shown below: Inspired by Kristen Graber - Berkner HS student 2005 // Java0912.java // JackO'lantern Case Study, Stage #1 // This program shows the <Pumpkin> class. import java.awt.*; import java.applet.*; public class Java0912 extends Applet { public void paint(Graphics g) { Pumpkin p = new Pumpkin(g); } } class Pumpkin { public Pumpkin(Graphics g) { g.setColor(Color.orange); g.fillOval(100,100,600,450); g.setColor(new Color(50,200,50)); g.fillRect(390,30,20,80); } } public void drawEyes(Graphics g) { g.setColor(Color.black); g.fillOval(200,200,100,100); g.fillOval(500,200,100,100); } // Java0913.java // JackO'lantern Case Study, Stage #2 // This program creates the <Face> class import java.awt.*; import java.applet.*; public void drawNose(Graphics g) { Polygon nose = new Polygon(); nose.addPoint(350,340); nose.addPoint(450,340); nose.addPoint(400,270); g.fillPolygon(nose); } public class Java0913 extends Applet { public void paint(Graphics g) { Face f = new Face(g); } } class Face { public Face(Graphics g) { drawEyes(g); drawNose(g); drawMouth(g); } public void drawMouth(Graphics g) { Polygon mouth = new Polygon(); mouth.addPoint(300,400); mouth.addPoint(200,350); mouth.addPoint(250,450); mouth.addPoint(400,500); mouth.addPoint(550,450); mouth.addPoint(600,350); mouth.addPoint(500,400); g.fillPolygon(mouth); } } // Java0914.java JackO'lantern Case Study, Stage #3 // This program demonstrates both inheritance and composition. // A JackO'lantern is-a Pumpkin. A JackO'lantern has-a face. import java.awt.*; import java.applet.*; public class Java0914 extends Applet { public void paint(Graphics g) { JackOlantern jack = new JackOlantern(g); } } class JackOlantern extends Pumpkin { private Face f; public JackOlantern(Graphics g) { super(g); f = new Face(g); } } class Pumpkin { public Pumpkin(Graphics g) { g.setColor(Color.orange); g.fillOval(100,100,600,450); g.setColor(new Color(50,200,50)); g.fillRect(390,30,20,80); } } class Face { // same as the last program } Train Case Study We will now look at a longer 6-step Case Study that will ultimately draw a Train. The end result is shown below: Inspired by Greg Muzljakovich and Amy Ho – BHS students 2005 // Java0915.java Train case study, Stage #1 // This program begins the <TrainCar> class. // The train car is blue and it is always drawn in the same place. import java.awt.*; import java.applet.*; public class Java0915 extends Applet { public void paint(Graphics g) { TrainCar tc = new TrainCar(g); } } class TrainCar { public TrainCar(Graphics g) { g.setColor(Color.blue); g.fillRect(325,250,150,100); g.setColor(Color.black); g.fillOval(330,325,50,50); g.fillOval(420,325,50,50); } } // Java0916.java // Train case study, Stage #2 // This program improves the TrainCar class by allowing a train car to be any color. import java.awt.*; import java.applet.*; public class Java0916 extends Applet { public void paint(Graphics g) { TrainCar tc = new TrainCar(g,Color.green); } } class TrainCar { private Color carColor; public TrainCar(Graphics g, Color cc) { carColor = cc; g.setColor(carColor); g.fillRect(325,250,150,100); g.setColor(Color.black); g.fillOval(330,325,50,50); g.fillOval(420,325,50,50); } } // Java0917.java // Train case study, Stage #3 // This program further improves the <TrainCar> class by // allowing train cars to be drawn in different locations. import java.awt.*; import java.applet.*; public class Java0917 extends Applet { public void paint(Graphics g) { TrainCar tc1 = new TrainCar(g,Color.blue,70); TrainCar tc2 = new TrainCar(g,Color.green,240); TrainCar tc3 = new TrainCar(g,Color.yellow,410); TrainCar tc4 = new TrainCar(g,Color.magenta,580); } } class TrainCar { private Color carColor; public TrainCar(Graphics g, Color cc, int x) { carColor = cc; g.setColor(carColor); g.fillRect(x,250,150,100); g.setColor(Color.black); g.fillOval(x+5,325,50,50); g.fillOval(x+95,325,50,50); } } // Java0918.java Train case study, Stage #4 // This program adds the <Locomotive> class. // A <Locomotive> is-a <TrainCar> class Locomotive extends TrainCar { private int x; public Locomotive(Graphics g, Color cc, int x1) { super(g,cc,x1); x = x1; drawScoop(g); drawFunnel(g); } import java.awt.*; import java.applet.*; public class Java0918 extends Applet { public void paint(Graphics g) { Locomotive loc = new Locomotive(g,Color.blue,70); } } public void drawScoop(Graphics g) { Polygon scoop = new Polygon(); scoop.addPoint(x,300); scoop.addPoint(x,350); scoop.addPoint(x-50,350); g.setColor(Color.black); g.fillPolygon(scoop); } class TrainCar { private Color carColor; public void drawFunnel(Graphics g) { Polygon funnel = new Polygon(); funnel.addPoint(x+20,250); funnel.addPoint(x+20,220); funnel.addPoint(x,200); funnel.addPoint(x,190); funnel.addPoint(x+60,190); funnel.addPoint(x+60,200); funnel.addPoint(x+40,220); funnel.addPoint(x+40,250); g.setColor(Color.black); g.fillPolygon(funnel); } public TrainCar(Graphics g, Color cc, int x) { carColor = cc; g.setColor(carColor); g.fillRect(x,250,150,100); g.setColor(Color.black); g.fillOval(x+5,325,50,50); g.fillOval(x+95,325,50,50); } } } // Java0919.java Train case study, Stage #5 // This program adds the <Caboose> class. // A caboose is a red train car with windows and a raised roof import java.awt.*; import java.applet.*; class Caboose extends TrainCar { private int x; public Caboose(Graphics g, int x1) { super(g,Color.red,x1); x = x1; drawWindows(g); drawTop(g); } public class Java0919 extends Applet { public void paint(Graphics g) { Caboose cab = new Caboose(g,580); } } public void drawWindows(Graphics g) { g.setColor(Color.white); g.fillRect(x+30,280,30,30); g.fillRect(x+90,280,30,30); } class TrainCar { private Color carColor; public TrainCar(Graphics g, Color cc, int x) { carColor = cc; g.setColor(carColor); g.fillRect(x,250,150,100); g.setColor(Color.black); g.fillOval(x+5,325,50,50); g.fillOval(x+95,325,50,50); } } public void drawTop(Graphics g) { g.setColor(Color.red); g.fillRect(x+30,235,90,15); g.setColor(Color.black); g.fillRect(x+25,235,100,5); } } // Java0920.java Train case study, Stage #6 // This program finally adds the <Train> class // A train has train cars. The first train car is the locomotive. The last train car is the Caboose. import java.awt.*; import java.applet.*; public class Java0920 extends Applet { public void paint(Graphics g) { Train t = new Train(g,55); } } class Train { private Locomotive loc; private TrainCar tc1; private TrainCar tc2; private TrainCar tc3; private TrainCar tc4; private Caboose cab; public Train(Graphics g, int x) { loc = new Locomotive(g,Color.blue,x); tc1 = new TrainCar(g,Color.green,x+160); tc2 = new TrainCar(g,Color.yellow,x+320); tc3 = new TrainCar(g,Color.magenta,x+480); tc4 = new TrainCar(g,Color.cyan,x+640); cab = new Caboose(g,x+800); } } // Java0921.java // This program demonstrates inheritance of three // sub classes with the same <Animal> superclass. public class Java0921 { public static void main(String args[]) { Cat tiger = new Cat("Tiger"); System.out.println(tiger.getType()); Bird eagle = new Bird("Eagle"); System.out.println(eagle.getType()); class Cat extends Animal { protected String catType; public Cat(String ct) { catType = ct; } public String getType() { return catType; } } class Bird extends Animal { protected String birdType; public Bird(String bt) { birdType = bt; } Fish shark = new Fish("Shark"); System.out.println(shark.getType()); public String getType() { return birdType; } } } } class Animal { public Animal() { System.out.println( "Animal constructor called"); } } class Fish extends Animal { protected String fishType; public Fish(String ft) { fishType = ft; } public String getType() { return fishType; } } // Java0922.java // This program demonstrates that it is // possible to use the super class identifier // <Animal> to declare each sub class object. public class Java0922 { public static void main(String args[]) { class Cat extends Animal { protected String catType; public Cat(String ct) { System.out.println("Cat constructor called"); catType = ct; } } class Bird extends Animal { protected String birdType; Animal eagle = new Bird("Eagle"); public Bird(String bt) { Animal shark = new Fish("Shark"); System.out.println("Bird constructor called"); } birdType = bt; } } } class Animal class Fish extends Animal { { public Animal() protected String fishType; { public Fish(String ft) System.out.println( { "Animal constructor called"); System.out.println("Fish constructor called"); fishType = ft; } } } } Animal tiger = new Cat("Tiger"); // Java0923.java // This program adds <getType> methods for each // one of the three <Animal> sub classes. // The program does not compile, because // <getType> is not an <Animal> method. public class Java0923 { public static void main(String args[]) { Animal tiger = new Cat("Tiger"); System.out.println(tiger.getType()); Animal eagle = new Bird("Eagle"); System.out.println(eagle.getType()); class Cat extends Animal { protected String catType; public Cat(String ct) { catType = ct; } public String getType() { return catType; } } class Bird extends Animal { protected String birdType; public Bird(String bt) { birdType = bt; } Animal shark = new Fish("Shark"); System.out.println(shark.getType()); } } class Animal { public Animal() { System.out.println( "Animal constructor called"); } } public String getType() { return birdType; } } class Fish extends Animal { protected String fishType; public Fish(String ft) { fishType = ft; } public String getType() { return fishType; } } // Java0924.java // This program solves the problem of the previous // program. Each <getType> method is "cast" to // the appropriate class. public class Java0924 { public static void main(String args[]) { Animal tiger = new Cat("Tiger"); System.out.println(((Cat)tiger).getType()); Animal eagle = new Bird("Eagle"); System.out.println(((Bird)eagle).getType()); Animal shark = new Fish("Shark"); System.out.println(((Fish)shark).getType()); } } class Animal { public Animal() { System.out.println( "Animal constructor called"); } } class Cat extends Animal { protected String catType; public Cat(String ct) { catType = ct; } public String getType() { return catType; } } class Bird extends Animal { protected String birdType; public Bird(String bt) { birdType = bt; } public String getType() { return birdType; } } class Fish extends Animal { protected String fishType; public Fish(String ft) { fishType = ft; } public String getType() { return fishType; } } // Java0925.java // This program demonstrates that it is possible // to use the super class identifier // <Object> to declare each sub class object. public class Java0925 { public static void main(String args[]) { class Cat extends Object { protected String catType; public Cat(String ct) { System.out.println("Cat constructor called"); catType = ct; } } class Bird extends Object { Object tiger = new Cat("Tiger"); protected String birdType; public Bird(String bt) Object eagle = new Bird("Eagle"); { System.out.println("Bird constructor called"); Object shark = new Fish("Shark"); birdType = bt; } } } } class Fish extends Object { protected String fishType; public Fish(String ft) { System.out.println("Fish constructor called"); fishType = ft; } } // Java0926.java // This program demonstrates that the <Object> // super class can be used like the <Animal> super // class with the proper type casting. class Cat { protected String catType; // It also shows that it is not necessary // to use "extends Object". public class Java0926 { public static void main(String args[]) { Object tiger = new Cat("Tiger"); System.out.println(((Cat)tiger).getType()); Object eagle = new Bird("Eagle"); System.out.println(((Bird)eagle).getType()); Object shark = new Fish("Shark"); System.out.println(((Fish)shark).getType()); } } public Cat(String ct) { catType = ct; } public String getType() { return catType; } } class Bird { protected String birdType; public Bird(String bt) { birdType = bt; } public String getType() { return birdType; } } class Fish { protected String fishType; public Fish(String ft) { fishType = ft; } public String getType() { return fishType; } } “The mother of all classes” All classes automatically inherit from The Object Class