CS100J, Fall 2001 Thurs 11/13 Lecture 21 ------------------------------------------------------------------------------- Announcements: + E9 due Thurs + P6 and makeup project: merged ------------------------------------------------------------------------------- Topics: + summary of inheriting public members + rules for constructors + Class $Object$ + order of construction + inheritance of public members continued ------------------------------------------------------------------------------- Constructors: + constructors NEVER inherit (not considered members of a class!) + subclass MUST call constructor of superclass + syntax: 1st line of subclass constructor must be $super$(args), $this$(args), or neither (which forces $super$() by default) (1) subclass constructor calls superclass constructor with $super$: - the supercalls MUST have a constructor that matches the arguments - use for setting values that are inherited/used by the subclass (2) subclass constructor calls a constructor in the SAME class with $this$: - constructors in the same class can call eachother with $this$(args) - the last constructor in the "chain" must call the superclass constructor (see (3) ). (3) subclass constructor calls $super$() by default: - happens when you do not write a $super$ or $this$ constructor call as the first line in the last subclass constructor that is called - if you wrote a non-empty constructor in the superclass, the superclass lost its default constructor (also called empty constructor) - if the superclass has NO empty constructor, you will get an error, so you need to ensure that the default constructor exists ------------------------------------------------------------------------------- // INHERIT2 (constructors) class A { public int x; public A(int x) { this.x=x; } } class B extends A { public int y; public B(int x) { super(x); this.y = x; } public B(int x,int y) { this(x); this.y = y; } } public class inherit2 { public static void main(String[] args) { B b1 = new B(1); System.out.println("1st: "+b1.x+" "+b1.y); B b2 = new B(2,3); System.out.println("2nd: "+b2.x+" "+b2.y); } } ------------------------------------------------------------------------------- ------------------------------------------------------------------------------- $Object$: + Every class in Java is a subclass of class $Object$. + don't usually write $extends Object$ in the class header, but you could: class Blah extends Object and class Blah mean the same thing! + $Object$ gives methods like $toString$ and $equals$ - for many of these methods, user must define method body for class - tells specific class how to handle the methods + where to find members of Object? - http://java.sun.com/j2se/1.4/docs/api/java/lang/Object.html - http://java.sun.com/j2se/1.4/docs/api/ + Example) Demostrate $toString$, $equals$, $clone$, and $getClass$. class A { public int x; public A(int x) { this.x = x; } public String toString() { return "x = " + x; } public boolean equals(A a) { return x == a.x; } public Object clone() { return new A(x); } } public class inherit17 { public static void main(String[] args) { A a1 = new A(1); A a2 = (A) a1.clone(); System.out.println(a1); // x = 1 System.out.println(a2); // x = 1 System.out.println(a1.equals(a2)); // true System.out.println(a1.getClass()); // class A } } ------------------------------------------------------------------------------- Rules for creating objects: + Java does the following when creating an object in this order: - allocate memory for the fields of the object (including inherited ones) - set ALL fields to default values ("zeros") - INVOKE each constructor in the chain of $this$ constructors (if necessary) (invoke now means to activate the constructor, but not execute the body) - invoke the superclass constructor (for more ancestors, all constructors are activated all the way "up") - all fields are initialized in the order that they're delared (top-down, then according to precedence/associativity) - the bodies of the constructors are activated from last to first (Java starts from Object and works its way back to the first constructor) + see inherit3.java ------------------------------------------------------------------------------- ------------------------------------------------------------------------------- Specialization of a class (Overriding, Shadowing): + subclasses specialize the behavior of the superclass - by adding methods to a subclass, it does something specific (yes, technically it is "wider" in terms of amounts of methods, but it's more specific because it contains methods that other subclasses do not) - you may also change the fields of a subclass! + ways to specialize: - OVERRIDING: changing the body of a method in a subclass + the super and subclasses have the same method headers + causes Java to use the overriden definition - SHADOWING: changing the fields in a subclass + forces Java to actually use the superclass version, sometimes! + not recommended! bad style! ------------------------------------------------------------------------------- Public methods: + syntax reminder: RULE2: Java uses the actual object to invoke public methods, not the reference type (ie, the class of the reference variable) - Java accesses public methods from the subclass even if the method is written and/or called in the superclass - also called dynamic binding/late binding/dynamic method lookup (Savitch 7.3) + RULE3: a method uses the fields from the class in which the method is written - since a public field is inherited, then Java thinks that the field is written in the subclass anyway - if the field is shadowed, then you must be very careful to keep track of the class in which the method is written - the class in which the method is written is where the method will find its fields + may override methods - write method in subclass with IDENTICAL header (same type, params, types, order, amount) - Java always use the version written in the subclass,assuming that the superclass version of the method COULD be inherited, (ie, it's public) - why? might need to change behavior in subclass from superclass + overriding vs overloading: override: same header -- call subclass's version overload: different header -- call current class's version ------------------------------------------------------------------------------- Public fields + syntax reminder: RULE 4: Java uses the type of the reference variable (assuming that there is one) that refers to a subclass object. - this rule applies when you are trying to access a field using a reference variable - generally, since most fields are made private, you don't usually get to use this rule. + SHADOWING: "overriding a field" (but not quite) - writing a field with the same name in a sub and superclass - bad style! but it's fun to teach! (syntactical curiosity) - RULE 3 applies: a method uses the fields from the class in which the method is written - RULE 4 may also apply if the fields are public. ------------------------------------------------------------------------------- ------------------------------------------------------------------------------- public class inherit_methods { public static void main(String[] args) { B b = new B(); b.print1(); b.print2(); } } class A { public int x=1; public A() { print1(); print2(); /* print3(); */} public void print1() { System.out.println(x+0); } public void print2() { System.out.println(x+1); } } class B extends A { public B() { print1(); print2(); print3(); } public void print2() { System.out.println(x+2); } public void print3() { System.out.println(x+3); } } /* Note: how to use A's implementation of print2? */ ------------------------------------------------------------------------------- public class inherit_shadow { public static void main(String[] args) { new B(); } } class A { public int x=1; public int y=2; public int z=3; public A() { print1(); print2(); print3(); } public void print1() { System.out.println(x); } public void print2() { System.out.println(y); } public void print3() { System.out.println(z); } } class B extends A { public double x=1.0; public double y=2.0; public B() { print1(); print2(); print3(); } public void print1() { System.out.println(x); } } -------------------------------------------------------------------------------