Title: Chap 5' Reusing classes Java Programming
1Chap 5. Reusing classes Java Programming 5
- Data Mining Lab, Lee Seung-Kyung
2Course Overview
- Java Programming 1. Introduction
- The way to use JAVA Eclipse for your
convenience - Simple program printing Hello, World no basic
knowledge , just code! - Java Programming 2. Introduction to Objects,
Everything is an object - Learning the Object-Oriented Programming Style
using JAVA - Java Programming 3. Controlling program flow
- Learning to manipulate objects data using
operators - Java Programming 4. Initialization and Cleanup
- Two safety issues Initialization (Before using
objects) Cleanup (After using objects)
3Introduction Reusing classes
- Reusing classes
- - using existing classes that someone has already
built and debugged - In this class youll see two ways to accomplish
this - Composition the new class is composed of
objects of existing classes - The first is quite straightforward You simply
create objects of your existing class inside the
new class. - Youre simply reusing the functionality of the
code, not its form. - Inheritance creating a new class as type of an
existing class - Inheritance is one of the cornerstones of
object-oriented programming - It has additional implications Polymorphism
4Composition Syntax
- Until now, composition has been used quite
frequently - You simply place object handles inside new
classes - For example,
- // Composition for code reuse
- class WaterSource
- private String s
- WaterSource()
- System.out.println("WaterSource()")
- s new String("Constructed")
-
- public String toString() return s
-
- public class SprinklerSystem
- private String valve1, valve2, valve3
- WaterSource source
- int i
- void print()
- System.out.println("valve1 " valve1)
5Composition Syntax
- In previous example,
- Primitives that are fields in a class are
automatically initialized to zero - The object handles are initialized to null
- If you try to call methods for any of them
youll get an exception - And then how printed??
- Its actually pretty good (and useful) that you
can still print them out without throwing an
exception - It makes sense that the compiler doesnt just
create a default object for every handle - At the point the objects are defined, theyll
always be initialized before the constructor is
called - This can reduce overhead, if there are
situations where the object doesnt need to be
created
6public class Bath private String //
Initializing at point of definition s1 new
String("Happy"), s2 "Happy", s3, s4
Soap castille int i Bath()
System.out.println("Inside Bath()") s3 new
String("Joy") i 47 castille new
Soap() void print() // Delayed
initialization if(s4 null) s4 new
String("Joy") System.out.println("s1 "
s1) System.out.println("s2 " s2)
System.out.println("s3 " s3)
System.out.println("s4 " s4)
System.out.println("i " i)
System.out.println("toy " toy)
System.out.println("castille " castille)
public static void main(String args)
Bath b new Bath() b.print() ///
Composition Syntax
// Constructor initialization with
composition class Soap private String s
Soap() System.out.println("Soap()") s
new String("Constructed") public String
toString() return s
When print( ) is called it fills in s4 so that
all the fields are properly initialized by the
time they are used
7Inheritance Syntax
- Inheritance has been used occasionally in
chapters before this one - Because certain situations required it
- In addition, youre always doing inheritance
when you create a class - because if you dont say otherwise you inherit
from Javas standard root class Object - When you inherit, you say This new class is
like that old class - You state this in code by giving the name of the
class as usual - Before the opening brace of the class body, put
the keyword extends followed by the name of the
base class - When you do this, you automatically get all the
data members and methods in the base class
8Inheritance Syntax
// Inheritance syntax properties class
Cleanser private String s new
String("Cleanser") public void append(String
a) s a public void dilute() append("
dilute()") public void apply() append("
apply()") public void scrub() append("
scrub()") public void print()
System.out.println(s) public static void
main(String args) Cleanser x new
Cleanser() x.dilute() x.apply()
x.scrub() x.print()
public class Detergent extends Cleanser //
Change a method public void scrub()
append(" Detergent.scrub()") // Call
base-class method super.scrub() // Call
base-class version // Add methods to the
interface public void foam() append("
foam()") // Test the new class public
static void main(String args) Detergent x
new Detergent() x.dilute()
x.apply() x.scrub() x.foam()
x.print() System.out.println("Testing base
class") Cleanser.main(args) ///
9Inheritance Syntax
- both Cleanser and Detergent contain a main( )
method - You can create a main( ) for each one of your
classes - Even if you have a lot of classes in a program
- Only the main( ) for the public class invoked
on the command line will be called - Its often recommended to code this way so that
your test code is wrapped in with the class - This technique of putting a main( ) in each
class allows easy unit testing for each class - Its important that all of the methods in
Cleanser are public - Detergent could access only public members
- A general rule make all fields private and all
methods public - protected members also allow access by derived
classes - append( ), dilute( ), apply( ), scrub( ) and
print( ) ? Reusing the interface - As seen in scrub( ), its possible to take a
method thats been defined in the base class and
modify it - You can also add new methods to the derived
class exactly the way you put any method in a
class
10Initializing the base class
- There are now two classes involved the base
class and the derived class instead of just one - The new class has the same interface as the base
class and some additional methods and fields - But inheritance doesnt just copy the interface
of the base class - When you create an object of the derived class,
it contains within it a sub-object of the base
class - From the outside, the sub-object of the base
class is wrapped within the derived-class object - Of course, its essential that the base-class
sub-object be initialized correctly - Theres only one way to guarantee that
- Perform the initialization in the constructor,
by calling the base-class constructor, which has
all the appropriate knowledge and privileges to
perform the base-class initialization - Java automatically inserts calls to the
base-class constructor in the derived-class
constructor
11Initializing the base class
// Constructor calls during inheritance class Art
Art() System.out.println("Art
constructor") class Drawing extends Art
Drawing() System.out.println("Drawing
constructor") public class Cartoon
extends Drawing Cartoon()
System.out.println("Cartoon constructor")
public static void main(String args)
Cartoon x new Cartoon() ///
You can see that the construction happens from
the base outward, so the base class is
initialized before the derived-class constructors
can access it
12Initializing the base class Constructors with
arguments
- The previous example has default constructors
that is, they dont have any arguments - Its easy for the compiler to call these because
theres no question about what arguments to pass - You must explicitly write the calls to the
base-class constructor using keyword super - The call to the base-class constructor must be
the first thing in the derived-class constructor
// Inheritance, constructors and arguments class
Game Game(int i) System.out.println("Gam
e constructor") class BoardGame extends
Game BoardGame(int i) super(i)
System.out.println("BoardGame constructor")
public class Chess extends BoardGame
Chess() super(11) System.out.println("C
hess constructor") public static void
main(String args) Chess x new Chess()
///
13Combining composition and inheritance
- It is very common to use composition and
inheritance together
// Combining composition inheritance class
Plate Plate(int i) System.out.println("P
late constructor") class DinnerPlate
extends Plate DinnerPlate(int i)
super(i) System.out.println("DinnerPlate
constructor") class Utensil
Utensil(int i) System.out.println("Utensil
constructor") class Spoon extends
Utensil Spoon(int i) super(i)
System.out.println("Spoon constructor")
class Fork extends Utensil Fork(int i)
super(i) System.out.println("Fork
constructor") class Knife extends Utensil
Knife(int i) super(i)
System.out.println("Knife constructor")
// A cultural way of doing something class
Custom Custom(int i) System.out.println(
"Custom constructor")
14Combining composition and inheritance
public class PlaceSetting extends Custom
Spoon sp Fork frk Knife kn DinnerPlate
pl PlaceSetting(int i) super(i 1)
sp new Spoon(i 2) frk new Fork(i
3) kn new Knife(i 4) pl new
DinnerPlate(i 5) System.out.println("Place
Setting constructor") public static void
main(String args) PlaceSetting x new
PlaceSetting(9) ///
15Name hiding
- If a Java base class has a method name thats
overloaded several times, - redefining that method name in the derived
class will not hide any of the base-class
versions - Thus overloading works regardless of whether the
method was defined at this level or in a base
class
// Overloading a base-class method name in a
derived class does not hide the base-class
versions class Homer char doh(char c)
System.out.println("doh(char)") return 'd'
float doh(float f) System.out.println("do
h(float)") return 1.0f class Milhouse
class Bart extends Homer void
doh(Milhouse m) class Hide public
static void main(String args) Bart b
new Bart() b.doh(1) // doh(float) used
b.doh('x') b.doh(1.0f) b.doh(new
Milhouse()) ///
16Choosing composition vs. inheritance
- Both composition and inheritance allow you to
place sub-objects inside your new class - What difference?
- Composition is generally used when you want the
features of an existing class inside your new
class, but not its interface - That is, you embed an object so that you can use
it to implement features of your new class, but
the user of your new class sees the interface
youve defined rather than the interface from the
embedded object - For this effect, you embed private objects of
existing classes inside your new class - Sometimes it makes sense to allow the class user
to directly access the composition of your new
class - that is, to make the member objects public
- The member objects use implementation hiding
themselves, so this is a safe thing to do - when the user knows youre assembling a bunch of
parts, it makes the interface easier to understand
17Choosing composition vs. inheritance
// Composition with public objects class Engine
public void start() public void rev()
public void stop() class Wheel
public void inflate(int psi) class Window
public void rollup() public void
rolldown() class Door public Window
window new Window() public void open()
public void close()
public class Car public Engine engine new
Engine() public Wheel wheel new Wheel4
public Door left new Door(), right new
Door() // 2-door Car() for(int i 0 i
lt 4 i) wheeli new Wheel()
public static void main(String args) Car
car new Car() car.left.window.rollup()
car.wheel0.inflate(72) ///
18Choosing composition vs. inheritance
- The composition of a car is part of the analysis
of the problem - The members public assists the client
programmers understanding of how to use the
class - and requires less code complexity for the
creator of the class - When you inherit, you take an existing class and
make a special version of it - It would make no sense to compose a car using a
vehicle object - The is-a relationship is expressed with
inheritance, - and the has-a relationship is expressed with
composition
19Protected
- In real projects, there are times when you want
to make something hidden from the world at large
and yet allow access for members of derived
classes - This is private as far as the class user is
concerned, - but available to anyone who inherits from this
class or anyone else in the same package.
// The protected keyword import
java.util. class Villain private int i
protected int read() return i protected
void set(int ii) i ii public
Villain(int ii) i ii public int
value(int m) return mi public class Orc
extends Villain private int j public
Orc(int jj) super(jj) j jj public void
change(int x) set(x) ///
20Incremental development
- One of the advantages of inheritance is that it
supports incremental development - Allowing you to introduce new code without
causing bugs in existing code - This also isolates new bugs to the new code
- You need to take a new look at your class
hierarchy - The is-a relationship is expressed with
inheritance, - The has-a relationship is expressed with
composition
21Upcasting
- The relationship expressed between the new class
and the base class - The new class is a type of the existing class
- The act of converting a Wind handle into an
Instrument handle is called upcasting - // Inheritance upcasting
- import java.util.
-
- class Instrument
- public void play()
- static void tune(Instrument i)
- // ...
- i.play()
-
-
-
- // Wind objects are instruments
- // because they have the same interface
- class Wind extends Instrument
- public static void main(String args)
22Why Upcasting
- The inheritance diagram of the previous example
- Casting from derived to base moves up on the
inheritance diagram upcasting - Upcasting is always safe because youre going
from a more specific type to a more general type
23The final keyword
- In general it says This cannot be changed
- You might want to prevent changes for two
reasons design or efficiency - Because these two reasons are quite different,
its possible to misuse the final keyword - the three places where final can be used for
data, methods and for a class
24Final data
- A piece of data is constant
- A constant is useful for two reasons
- It can be a compile-time constant that wont
ever change - the calculation can be performed at compile
time, eliminating some run-time overhead - these sorts of constants must be primitives and
are expressed using the final keyword - It can be a value initialized at run-time that
you dont want changed - A field that is both static and final has only
one piece of storage that cannot be changed - With a primitive, final makes the value a
constant - With an object handle, final makes the handle a
constant - The handle must be initialized to an object at
the point of declaration - The handle can never be changed to point to
another object - However, the object can be modified
25Final data
// The effect of final on fields class Value
int i 1 public class FinalData // Can
be compile-time constants final int i1 9
static final int I2 99 // Typical public
constant public static final int I3 39
// Cannot be compile-time constants final int
i4 (int)(Math.random()20) static final int
i5 (int)(Math.random()20) Value v1 new
Value() final Value v2 new Value() static
final Value v3 new Value() //! final
Value v4 // Pre-Java 1.1 Error no initializer
// Arrays final int a 1, 2, 3, 4, 5, 6
public void print(String id)
System.out.println( id " " "i4 "
i4 ", i5 " i5)
public static void main(String args)
FinalData fd1 new FinalData() //!
fd1.i1 // Error can't change value
fd1.v2.i // Object isn't constant!
fd1.v1 new Value() // OK -- not final
for(int i 0 i lt fd1.a.length i)
fd1.ai // Object isn't constant! //!
fd1.v2 new Value() // Error Can't //!
fd1.v3 new Value() // change handle //!
fd1.a new int3 fd1.print("fd1")
System.out.println("Creating new FinalData")
FinalData fd2 new FinalData()
fd1.print("fd1") fd2.print("fd2") //
the difference between final with static /
non-static ///
26Final methods
- There are two reasons for final methods
- The first is to put a lock on the method to
prevent any inheriting class from changing its
meaning - The second reason for final methods is
efficiency - If you make a method final, you allow the
compiler to turn any calls to that method into
inline calls - The compiler replaces the method call with a
copy of the actual code in the method body - This eliminates the overhead of the method call
- Any private methods in a class are implicitly
final - You can add the final to a private method but it
doesnt give that method any extra meaning
27Final classes
- An entire class is final you dont want to
inherit from this class or allow anyone else to
do so - // Making an entire class final
- class SmallBrain
-
- final class Dinosaur
- int i 7
- int j 1
- SmallBrain x new SmallBrain()
- void f()
-
-
- //! class Further extends Dinosaur
- // error Cannot extend final class 'Dinosaur'
-
- public class Jurassic
- public static void main(String args)
- Dinosaur n new Dinosaur()
- n.f()
28Exercises 1. Create two classes, A and B, with
default constructors (empty argument lists) that
announce themselves. Inherit a new class called C
from A, and create a member B inside C. Do not
create a constructor for C. Create an object of
class C and observe the results. (25) 2. Modify
Exercise 1 so that A and B have constructors with
arguments instead of default constructors. Write
a constructor for C and perform all
initialization within Cs constructor. (25)
29Homework 4
- Be Careful of Below Policy (Upgraded Policy.
Check it out!!!!) - Subject of E-mail IIC2009_StduentNumber_Name_
HW4.zip - Including following Java Files and Report
- Homework4_1.java / Homework4_2.java
- Report.doc
- Report
- Result and Explanation
- Simple and Clear
- Due 1200 p.m 2009-05-18 (I give you more time
read the class material first!!!! There is the
solution) - E-Mail to sklee83_at_snu.ac.kr
- Points
- Problem 1 25 Points
- Problem 2 25 Points
- Report 20 Points