Inheritance

Object Composition

public class PetDemo {
    public static void main(String[] argv) {
        Person mary = new Person(); 
        mary.name = "Mary"; 
        mary.pet = new Pet(); 
        mary.pet.type = "little lamb"; 
        mary.sing();
    }
}

class Person { 
    String name; 
    Pet pet; 
    void sing() {
        System.out.print(name + " has a " + pet.type + ", "); 
        System.out.println(pet.type + ", " + pet.type + "."); 
    }
}

class Pet { 
    String type; 
}

A basic way of re-using variables/methods in other classes.

class User {
    int money;

    void talk_to_friend(User a_user) { 
    }
}

class SYSOP extends User {
    //money "inherited" from the definition above
    //talk_to_friend "inherited" from the definition above

    void reset_user_money(User a_user) { 
        a_user.money = 0; 
    }
    
    //reset_sysop_money no need, because SYSOP is a User 
}

Inheritance

Another way of reusing code.

Taxonomy

More Is-A...

class CassettePlayer { 
    void play(Cassete c) { 
    }
}
 
class CDandCassettePlayer extends CassettePlayer{ 
    //play (Cassete) inherited 
    void play (CD c){ }
}

CDandCassetePlayer is a (extended) CassetePlayer.

class Player { 
    void play() { 
    }
}

class CassettePlayer extends Player { 
    void play(Cassete c) { 
        insert(c); 
        play();
}
 
class CDPlayer extends Player { 
    void play(CD c) { 
        insert(c);
        play();
    }
}

CassetePlayer is a (concrete description of) Player.

CDPlayer is a (concrete description of) Player.

class CassettePlayer { 
    void play(Cassette c) {
    }
}
 
class CDPlayer extends CassettePlayer {
    void play(Cassette c) {
        System.out.println("I cannot play Cassette");
    } 
    void play(CD c) {
    }
}

CD player is a (update of) CassetePlayer.

Override

class Player { 
    void play() {
    }
}

class CassettePlayer extends Player {
    void play(Cassette c) { 
        insert(c); 
        play();
    }
}

class CDPlayer extends Player {
    void play(CD c) {
        insert(c); 
        play();
}

class CDandCassettePlayer extends CassettePlayer and CDPlayer { 
    //play (Cassete) inherited 
    //play (CD) inherited
}

Multiple inheritance is not supported in Java.

Instance Variable & Inheritance

class Professor { 
    public String name; 
    
    public String get_name() { 
        return name;
    }
}

class CSIEProfessor extends Professor{ 
    public int office_number;
 
    public int get_office_number() { 
        return office_number;
    }
}

CSIEProfessor: 2 instance variables.

Professor: 1 instance variable.

class Professor {
    public String name = "professor";
 
    public String get_name() {
        return name;
    }
}

class CSIEProfessor extends Professor { 
    public String name = "csie_professor"; //?! 
    public int office_number;

    public int get_office_number() {
        return office_number;
    }
    public String get_this_name() { 
        return name;
    }
}

/*  CSIEProfessor HTLin = new CSIEProfessor();
    Professor HTLin = new CSIEProfessor(); 
    Professor HTLin = new Professor(); 

    System.out.println(HTLin.get_name()); 
    System.out.println(HTLin.get_this_name()); 
    System.out.println(HTLin.name);
*/

CSIEProfessor: 3 instance variables.

Professor: 1 instance variable.

class Professor { 
    public String p_name; 
    public String get_name() { 
        return p_name;
    }
}

class CSIEProfessor extends Professor { 
    public String c_name;
    public int office_number; 

    public int get_office_number() { 
        return office_number;
    } 
    public String get_this_name() { 
        return c_name;
    }
}

An (almost) equivalent view of what the compiler sees.

Instance Variable Binding:

determined at compile time.

Instance Methods & Inheritance

class Professor { 
    public void say_hello() { 
        System.out.println("Hello!");
    }
}
 
class CSIEProfessor extends Professor { 
    public void play_BBS() { 
        System.out.println("Fun!");
    }
}

CSIEProfessor: 2 instance methods.

Professor: 1 instance method.

class Professor { 
    public void say_hello() {
        System.out.println("Hello!");
    }
}
 
class CSIEProfessor extends Professor{ 
    public void say_hello() {
        System.out.println("May the OOP course be with you!"); 
    }
}
//Try this.
CSIEProfessor HTLin1 = new CSIEProfessor();
Professor HTLin2 = new CSIEProfessor();
Professor HTLin3 = new Professor();

HTLin1.say_hello();
HTLin1.say_hello();
HTLin1.say_hello();

Outputs?

May the OOP course be with you!

May the OOP course be with you!

Hello!

Instance Method Binding:

determined at run-time.

Constructor & Inheritance

class Student { 
    int ID;
    String name;

    Student(int ID, String name) { 
        this.ID = ID;
        this.name = name;
    }
}

class AwardStudent extends Student { 
    Award[] awards;
    AwardStudent(int ID, String name, int nAward) { 
        super(ID , name); //means invoke Student(ID ,name); 
        //any utility function in Student can be used at this stage.
        awards = new Award[nAward]; 
    }
}

Initialize the ancestor part first.

class Student { 
    int ID;
    String name;

    Student(int ID, String name) { 
        this.ID = ID;
        this.name = name;
    }
}

class AwardStudent extends Student { 
    Award[] awards;
    AwardStudent(int ID, String name, int nAward) { 
        awards = new Award[nAward]; 
    }
}

super() automatically added if no explicit call in the beginning.

 Constructor call must be the first statement in the constructor.

But what if you add super() after awards = new Award[nAward] ? 

Error: Implicit super constructor Student() is undefined.

class Record{ 
    String name; 
    int score;

    Record(int init_score) {
        score = init_score;
    }

    Record() { 
        this(40);
    }
 
public class RecordDemo{ 
    public static void main(String[] arg) {
        Record r1 = new Record(60); 
        Record r2 = new Record(); 
        System.out.println(r1.score); 
        System.out.println(r2.score);
    }
}

One constructor can only call one other constructor (via this or super).

More on Super...

class Student { 
    int ID;
    String name; 
    
    void study_for_midterm() { 
        System.out.println("I_am_studying_for_midterm.");
    }
}
 
class AwardStudent extends Student { 
    Award [] president_awards; 

    void study_for_midterm() { 
        for(int i = 0; i < 10; i ++) 
            super.study_for_midterm();
    }
}

But no "super.super"

Private Variables & Inheritance

class Parent{ 
    private int hidden_money;
 
    public void show_hidden_money_amount() {
        System.out.println(hidden_money);
    }
}
 
class Child extends Parent { 
    void spend_money() { 
        //Q1: Can hidden_money money be spent here? 
        //Q2: Does Child have a hidden_money slot in the memory?
        //Q3: Can show_hidden_money_amount() be called here?
    }
}

Private variables are still "inherited" in memory, but not "visible" to the subclass because of encapsualtion.

Not directly.

Yes.

Yes.

Private Methods & Inheritance

class Parent { 
    private int hidden_money;

    private void buy_liquor() {
    } 

    public void show_hidden_money_amount() {
    }

class Child extends Parent {
    void buy() { 
        //Can buy_liquor() be called here?
    }
}

Private methods effectively not inherited.

No.

Access Permissions

package generation.old; 

public class Parent { 
    private int hidden_money;

    public void show_hidden_money_amount() {
    }

    void middle_age_issues() {
    }
 
    void cross_gen_issues() {
    }
}

 
//in a different file, Child.java 
package generation.new;
public class Child extends Parent {
}

Can hidden_money be accessed?

No.

Yes.

No.

No.

And what if we want "yes"?

Can show_hidden_money_amount be accessed?

Can middle_age_issues be accessed?

Can cross_gen_issues be accessed?

In class Child...

package generation.old; 

public class Parent { 
    private int hidden_money;

    public void show_hidden_money_amount() {
    }

    /*default*/ void middle_age_issues() {}; 
    protected void cross_gen_issues() {};
}

 
//in a different file, Child.java 
package generation.new;
public class Child extends Parent {
}

Protected: accessible to sub-classes and same-package-classes.

No.

Yes.

Default: accessible to same-package-classes only.

Can middle_age_issues be accessed?

Can cross_gen_issues be accessed?

In class Child...

Public: Accessible to everyone.

Protected: Accessible to sub-classes and same-package-classes.

(Default): Accessbile to same-package-classes.

Private: Accessible within it's own class definitions.

 

Access Level Modifiers

Also called Inner Class.

In the same file, only the one same with file's name can be public, however, all of them are default is acceptable.

  • At the top level—public, or default.
  • At the member level—public, private, protected, or default.

But when it comes to Class...

At Top Level

At Member Level

Inner Class

1. Static Nested Classes

2. Member Inner Class

3. Method-Local Inner Classes

4. Anonymous Inner Classes

Static Nested Classes

class Outer {
    static class Inner {
        void go() {
	    System.out.println("Inner class reference is: " + this);
	}
    }
}
 
public class Test {
    public static void main(String[] args) {
	Outer.Inner n = new Outer.Inner();
	n.go();
    }
}

Inner class reference is: Outer$Inner@19e7ce87

Member Inner Class

public class Outer {
    private int x = 100;
 
    public void makeInner() {
        Inner in = new Inner();
        in.seeOuter();
    }
 
    class Inner {
        public void seeOuter(){
            System.out.println("Outer x is " + x);
            System.out.println("Inner class reference is " + this);
            System.out.println("Outer class reference is " + Outer.this);
        }
    }
 
    public static void main(String [] args) {
    	Outer o = new Outer();
        Inner i = o.new Inner();
        i.seeOuter();
    }
}

Outer x is 100

Inner class reference is Outer$Inner@4dfd9726

Outer class reference is Outer@43ce67ca

Method-Local Inner Classes

public class Outer {
    private String x = "outer";
 
    public void doStuff() {
        class MyInner {
            public void seeOuter() {
                System.out.println("x is " + x);
	    }
	}
 
	MyInner i = new MyInner();
	i.seeOuter();
    }
 
    public static void main(String[] args) {
	Outer o = new Outer();
	o.doStuff();
    }
}

x is outer

public class Outer {
    private static String x = "static outer";
 
    public static void doStuff() {
	class MyInner {
	    public void seeOuter() {
		System.out.println("x is " + x);
	    }
	}
 
	MyInner i = new MyInner();
	i.seeOuter();
    }
 
    public static void main(String[] args) {
	Outer.doStuff();
    }
}

x is static outer.

Anonymous Inner Classes

button.addActionListener(new ActionListener() {
     public void actionPerformed(ActionEvent e){
         comp.setText("Button has been clicked");
     }
});

This is frequently used when you add an action listener to a widget in a GUI application.

Permissions and Method Overriding

public class Parent { 
    protected void method() { } 
}

class Child extends Parent { 
    private void method() { }
}
  
//bottom line 
Parent var = new Child(); 
var.method();
public class Parent { 
    protected void method() { } 
}

class Child extends Parent { 
    public void method() { } 
}
  
//bottom line 
Parent var = new Child(); 
var.method();

Cannot reduce visibility of the inherited method from Parent.

Calling Child's method.

Inheritance

package com.soc

class Professor{ }
class CSIEProfessor extends Professor{ } 
class EEProfessor extends Professor{ }
 
class Demo { 
    public static void main(String[] argv) { 
        CSIEProfessor HTLin = new CSIEProfessor(); 
        System.out.println(HTLin.getClass()); 
        System.out.println(HTLin instanceof CSIEProfessor); 
        System.out.println(HTLin instanceof Professor); 
        System.out.println(HTLin instanceof EEProfessor);
    }
}

class soc.CSIEProfessor

True.

True.

Compile error.

package com.soc

class Professor{ }
class CSIEProfessor extends Professor{ } 
class EEProfessor extends Professor{ }
 
class Demo { 
    public static void main(String[] argv) { 
        Professor HTLin = new CSIEProfessor(); 
        System.out.println(HTLin.getClass()); 
        System.out.println(HTLin instanceof CSIEProfessor); 
        System.out.println(HTLin instanceof Professor); 
        System.out.println(HTLin instanceof EEProfessor);
    }
}

Run-time error.

class soc.CSIEProfessor

True.

True.

class Professor { } 
class CSIEProfessor extends Professor { } 
class EEProfessor extends Professor } 

class Demo { 
    public static void main(String[] argv){ 
        Professor HTLin = new CSIEProfessor(); 
        int score = 100; 
        System.out.println(HTLin.getClass());
        System.out.println(score.getClass()); 
        System.out.println(HTLin instanceof java.lang.Object); 
        System.out.println(score instanceof Java.lang.Object); 
    }
}

Every valid object is an instance of java.lang.Object.

Primitive type is not an instance of anything.

Compile error.

class soc.CSIEProfessor

True.

False.

class Professor { } 
class CSIEProfessor extends Professor { } 
class EEProfessor extends Professor { }
 
class Demo { 
    public static void main(String[] argv) { 
        Professor[] parr = new CSIEProfessor[3];
 
        System.out.println(parr.getClass()); 
        System.out.println(parr instanceof Object); 
        System.out.println(parr instanceof Object[]); 
        System.out.println(parr instanceof Professor[]); 
        System.out.println(parr instanceof CSIEProfessor[]); 
        System.out.println(parr instanceof EEProfessor[]);
    }
}

Every object array is an instance of Object[].

Object[] is a reference type.

 Every reference type "extends" Object.

Every object array is an instance of Object. 

True.

True.

True.

True.

False.

[Lpackage_name.CSIEProfessor

class Demo { 
    public static void main(String[] argv) { 
        int [] oarr = new int[3];
        System.out.println(oarr.getClass()); 
        System.out.println(oarr instanceof Object); 
        System.out.println(oarr instanceof Object[]); 
        System.out.println(oarr instanceof double[]); 
        System.out.println(oarr instanceof short[]); 
        System.out.println(oarr instanceof int[]);
    }
}

A int array is an instance of int[].

int[] is a reference type.

Every reference type "extends" Object.

Every object array is an instance of Object.

Compile error.

True.

class [I.

True.

Compile error.

Compile error.

Assignment:  A Battlefield

Please design a RPG game logic.

  1. This game should contains at least 4 character: warrior, magician, archer and necromancer.
  2. Warrior and archer can only attack one enemy at one time while magician and necromancer can attack all character at one time.
  3. Please print out message everytime someone is attacking.
  4. The rest game logics is up to you.

Rules:

The output should be like this

Archer Legolas is attacking...
Magician Gandalf lost 20 life.

Warrior Aragorn is attacking...
Archer Legolas lost 30 life.

Magician Gandalf is attacking...
Archer Legolas lost 40 life.
Warrior Aragorn lost 40 life.
Necromancer Sauron dodged.

Archer Legolas is attacking...
Warrior Aragorn lost 20 life.

Warrior Aragorn is attacking...
Archer Legolas lost 30 life.
...Archer Legolas died.

Necromancer Sauron is attacking...
Warrior Aragorn lost 70 life.
Magician Gandalf lost 70 life.
...Warrior Aragorn died.
...Magician Gandalf died.

Necromancer Sauron rules the world!!!

The inheritance relation reference

Inheritance

By TingSheng Lee

Inheritance

  • 346