7:%20Polymorphism - PowerPoint PPT Presentation

About This Presentation
Title:

7:%20Polymorphism

Description:

So how can the compiler possibly know that this Instrument reference points to a Wind in this case and not a Brass or ... out.println( – PowerPoint PPT presentation

Number of Views:91
Avg rating:3.0/5.0
Slides: 19
Provided by: chen123
Category:

less

Transcript and Presenter's Notes

Title: 7:%20Polymorphism


1
7 Polymorphism
  • Upcasting revisited
  • Forgetting the object type
  • The twist
  • Method-call binding
  • Producing the right behavior
  • Extensibility
  • Overriding vs. overloading
  • Abstract classes and methods
  • Constructors and polymorphism
  • Designing with inheritance
  • Exercises

2
7 Polymorphism
  • Polymorphism is the third essential feature of an
    object-oriented programming language, after data
    abstraction and inheritance.

3
7 Polymorphism
  • // Wind objects are instruments
  • // because they have the same interface
  • class Wind extends Instrument
  • // Redefine interface method
  • public void play(Note n)
  • System.out.println("Wind.play()")
  • public class Music
  • public static void tune(Instrument i)
  • i.play(Note.MIDDLE_C)
  • public static void main(String args)
  • Wind flute new Wind()
  • tune(flute) // Upcasting

class Note private int value private
Note(int val) value val public static
final Note MIDDLE_C new Note(0),
C_SHARP new Note(1), B_FLAT new
Note(2) // Etc. class Instrument public
void play(Note n) System.out.println("Instrum
ent.play()")
4
The twist
  • The difficulty with Music.java can be seen by
    running the program. The output is Wind.play( ).
    This is clearly the desired output, but it
    doesnt seem to make sense that it would work
    that way. Look at the tune( ) method
  • public static void tune(Instrument i) // ...
    i.play(Note.MIDDLE_C)
  • It receives an Instrument reference. So how can
    the compiler possibly know that this Instrument
    reference points to a Wind in this case and not a
    Brass or Stringed? The compiler cant.

5
Method-call binding
  • Connecting a method call to a method body is
    called binding.
  • early binding When binding is performed before
    the program is run (by the compiler and linker)
  • You might not have heard the term before because
    it has never been an option with procedural
    languages.
  • C compilers have only one kind of method call,
    and thats early binding.
  • late binding means that the binding occurs at
    run-time based on the type of object.
  • Late binding is also called dynamic binding or
    run-time binding.
  • There must be some mechanism to determine the
    type of the object at run-time and to call the
    appropriate method.
  • The compiler still doesnt know the object type.

6
Producing the right behavior
  • The classic example in OOP is the shape
    example. This is commonly used because it is easy
    to visualize.

7
  • class Shape
  • void draw()
  • void erase()
  • class Circle extends Shape
  • void draw() System.out.println("Circle.draw()")
    void erase() System.out.println("Circle.eras
    e()")
  • class Square extends Shape
  • void draw() System.out.println("Square.draw()")
    void erase() System.out.println("Square.eras
    e()")
  • class Triangle extends Shape
  • void draw() System.out.println("Triangle.draw()
    ") void erase() System.out.println("Triangle.
    erase()")

public class Shapes public static Shape
randShape() // Upcasting switch((int)(Math
.random() 3)) default case 0 return new
Circle() case 1 return new Square() case
2 return new Triangle() public
static void main(String args) Shape s
new Shape9 // Fill up the array with
shapes for(int i 0 i lt s.length i)
si randShape() // Make polymorphic
method calls for(int i 0 i lt s.length i)
si.draw() /// Circle.draw()
Triangle.draw() Circle.draw() Circle.draw()
Circle.draw() Square.draw() Triangle.draw()
Square.draw() Square.draw()
8
Exercise
  • class Shape
  • void draw()
  • void erase()
  • void flash() draw() erase() draw()
  • class Circle extends Shape
  • void draw() System.out.println("Circle.draw()")
  • void erase() System.out.println("Circle.erase()
    ")
  • class Square extends Shape
  • void draw() System.out.println("Square.draw()")
  • void erase() System.out.println("Square.erase()
    ")
  • class Triangle extends Shape
  • void draw() System.out.println("Triangle.draw()
    ")
  • void erase() System.out.println("Triangle.erase
    ()")
  • public class Shapes ?main
  • for(int i 0 i lt s.length i) si. flash()

9
Extensibility
  • Because of polymorphism, you can add as many new
    types as you want to the system without changing
    the tune( ) method.
  • All these new classes work correctly with the
    old, unchanged tune( ) method.

10
  • import java.util.
  • class Instrument
  • public void play() System.out.println("Instrume
    nt.play()")
  • public String what() return "Instrument"
  • public void adjust()
  • class Wind extends Instrument
  • public void play() System.out.println("Wind.pla
    y()")
  • public String what() return "Wind"
  • public void adjust()
  • class Percussion extends Instrument
  • public void play() System.out.println("Percussi
    on.play()")
  • public String what() return "Percussion"
  • public void adjust()

class Stringed extends Instrument class
Woodwind extends Wind class Brass extends
Wind public
class Music3 // Doesn't care about type, so
new types static void tune(Instrument i) //
... i.play() static void tuneAll(Instrument
e) for(int i 0 i lt e.length i)
tune(ei) public static void
main(String args) Instrument orchestra
new Instrument5 int i 0 //
Upcasting during addition to the array
orchestrai new Wind() orchestrai
new Percussion() orchestrai new
Stringed() orchestrai new Brass()
orchestrai new Woodwind()
tuneAll(orchestra) ///
11
Overriding vs. overloading
  • class NoteX
  • public static final int MIDDLE_C 0, C_SHARP
    1, C_FLAT 2
  • class InstrumentX
  • public void play(int NoteX) System.out.println(
    "InstrumentX.play()")
  • class WindX extends InstrumentX
  • // OOPS! Changes the method interface
  • public void play(NoteX n) System.out.println("
    WindX.play(NoteX n)")
  • public class WindError
  • public static void tune(InstrumentX i)
    i.play(NoteX.MIDDLE_C)
  • public static void main(String args)
  • WindX flute new WindX()
  • tune(flute) // Not the desired behavior!
  • ///

12
Abstract classes and methods
  • In above examples, the methods in the base class
    Instrument were always dummy methods.
  • If these methods are ever called, youve done
    something wrong.
  • The intent of Instrument is to create a common
    interface for all the classes derived from it.
  • Java provides a mechanism for doing this called
    the abstract method. A class containing abstract
    method is a abstract class.
  • abstract method is a method that is incomplete
    it has only a declaration and no method body.
  • abstract void f()
  • It cannot create an object of an abstract class
  • If you inherit from an abstract class and you
    want to make objects of the new type, you must
    override (redefine) all the abstract methods in
    the base class.
  • If you dont (and you may choose not to), then
    the derived class is also abstract.

13
Abstract classes and methods
  • import java.util.
  • abstract class Instrument
  • int i // storage allocated for each
  • public abstract void play()
  • public String what() return "Instrument"
  • public abstract void adjust()
  • class Wind extends Instrument
  • public void play()
  • System.out.println("Wind.play()")
  • public String what() return "Wind"
  • public void adjust()

14
Designing with inheritance
  • Once you learn about polymorphism, it can seem
    that everything ought to be inherited because
    polymorphism is such a clever tool. This can
    burden your designs
  • A better approach is to choose composition first,
    when its not obvious which one you should use.
  • A Stage object contains a reference to an Actor,
    which is initialized to a HappyActor object. At
    run-time, a reference for a SadActor object can
    be substituted in a and then the behavior
    produced by go( ) changes.
  • Thus you gain dynamic flexibility at run-time.
    (This is also called the State Pattern. )

15
Designing with inheritance
  • // Dynamically changing the behavior of // an
    object via composition.
  • abstract class Actor
  • abstract void act()
  • class HappyActor extends Actor
  • public void act() System.out.println("HappyActo
    r")
  • class SadActor extends Actor
  • public void act() System.out.println("SadActor"
    )
  • class Stage
  • Actor a new HappyActor()
  • void change() a new SadActor()
  • void go() a.act()
  • public class Transmogrify
  • public static void main(String args)
  • Stage s new Stage()
  • s.go() // Prints "HappyActor"

16
Downcasting and run-time type identification
  • While upcasting is a useful and sensible approach
    (depending on the situation) it has a drawback.
    The extended part of the interface in the derived
    class is not available from the base class, so
    once you upcast you cant call the new methods

17
Downcasting and run-time type identification
  • import java.util.
  • class Useful
  • public void f()
  • public void g()
  • class MoreUseful extends Useful
  • public void f()
  • public void g()
  • public void u()
  • public void v()
  • public void w()

import java.util. public class RTTI public
static void main(String args) Useful x
new Useful(), new MoreUseful() x0.f()
x1.g() // Compile-time method not found
in Useful //! x1.u() //
Downcast/RTTI ((MoreUseful)x1).u() //
Exception thrown ((MoreUseful)x0).u()
///
18
Downcasting and run-time type identification
  • Since you lose the specific type information via
    an upcast (moving up the inheritance hierarchy),
    you can use a downcast to retrieve the type
    information (moving down the inheritance
    hierarchy )
  • An upcast is always safe
  • the base class cannot have a bigger interface
    than the derived class, therefore every message
    you send through the base class interface is
    guaranteed to be accepted.
  • But a downcast is unsafe,
  • A shape (for example) may be a circle or a
    triangle or a square or some other type.
  • In Java every cast is checked!
  • At run-time this cast is checked to ensure that
    it is in fact the type you think it is.
  • If it isnt, you get a ClassCastException. This
    act of checking types at run-time is called
    run-time type identification (RTTI).
Write a Comment
User Comments (0)
About PowerShow.com