CSC 335 ObjectOriented Programming and Design Rick Mercer
CSC 335 Object-Oriented Programming and Design ©Rick Mercer Some uses of Inheritance: A Review
1) Capture Common Behavior class Object w Java's Object class captures things that are common to all objects in Java. For example — Object's constructor communicates with the operating system to allocate memory at runtime • public Object() is called for every new object w Object is the root of all other classes — All classes extend Object — Before your constructor executes, super() is called which calls Object's constructor, even with this code class A {} new A(); 2
Empty. Class inherits the methods of Object // This class inherits Object's 11 methods public class Empty. Class extends Object { // Call Object’s constructor explicitly super(); // In absence of super(), it’s done implicitly } // Empty. Class passes messages to Object Empty. Class one = new Empty. Class(); System. out. println(one. to. String()); to. String System. out. println(one. hash. Code()); hash. Code System. out. println(one. get. Class()); get. Class System. out. println(one. equals(one)); equals 3
2) Inheritance helps with the Swing framework w Inheritance allows one class obtains behavior (methods) and attributes (instance variables) from an existing class get something for nothing class Im. AJFrame 2 extends JFrame { } 4
Inherit methods and fields class Im. AJFrame 2 extends JFrame { } import javax. swing. JFrame; public class Try 2 JFrames { public static void main(String[] args) JFrame window 1 = new JFrame(); window 1. set. Title("I'm a JFrame"); window 1. set. Size(200, 100); window 1. set. Location(10, 0); window 1. set. Visible(true); } { Im. AJFrame 2 window 2 = new Im. AJFrame 2(); window 2. set. Title("I'm a JFrame too"); window 2. set. Size(200, 100); window 2. set. Location(210, 0); window 2. set. Visible(true); } Who has the instance variables for the size and location? 5
Has-A and Is-A relationships w “HAS-A” relationships represent containment within an object; realized by instance variables public class My. List implements List. Model { private List<Songs> things; } — My. List object “has-a” List in it, and therefore can use it w “IS-A” relationships represent supersets of abilities; realized by inheritance — Im. AJFrame 2 IS-A Jframe For depth of the Component inheritance hierarchy, see JButton in the API 6
3) Java's Exception Hierarchy w Exceptions handle weird and awkward things — Some are standard exceptions that must be • caught with try and catch blocks, • or declared to be thrown in every method – The read message won’t compile unless you do one or the other public static void main(String[] args) { try { System. in. read(); } catch(IOException e) { System. out. println("read went wrong"); } } 7
Object Throwable Part of the Throwable inheritance hierarchy For the depth of this hierarchy, see Array. Index. Out. Of. Bounds. Exception Error IOException Run. Time. Exception File. Not. Found. Exception EOFException Null. Pointer. Exception Index. Out. Of. Bounds. Exception Array. Index. Out. Of. Bounds. Exception 8
Base and derived classes w Object is the super class of all classes w The Throwable class is the superclass of all errors and exceptions in the Java language w Error indicates serious problems that a reasonable application should not try to catch. w Exception and its subclasses are a form of Throwable that indicates conditions that a reasonable application might want to catch For the depth of this hierarchy, see Array. Index. Out. Of. Bounds. Exception 9
4) Our own Exception classes w A method can throw an existing exception /** * @return element at the top of this stack */ public E top() throws Empty. Stack. Exception { // The Empty. Stack. Exception is in java. util. *; if(this. Empty()) throw new Empty. Stack. Exception(); // If this stack is empty, return doesn't happen return my. Data. get. First(); } w Declare what the method throws, then throw a new exception -- The superclass constructor does the work 10
Writing our own Exception classes w Consider a Unplayable. Song. Exception method in class Play. List to inform users they sent a queue. Up message when the song play has maxed out public void queue. Up(Song song) throws Unplayable. Song. Exception { if (! song. can. Play. Today()) throw new Unplayable. Song. Exception (); //. . . } w You could start from scratch — find the line number, the file name, the methods, … • Or you could extend Run. Time. Exception class 11
Create a new Exception // // The work of exception handling will be extended to our new Unplayable. Song. Exception. All we have to do is implement one or two constructors that calls the superclass's constructor (Runtime. Exception here) with super. class Unplayable. Song. Exception extends Runtime. Exception { public Unplayable. Song. Exception () { // Send a message to Runtime. Exception() constructor super(); } public Unplayable. Song. Exception (String error. Message) { // Allow user to add their own message super(error. Message); } } super calls the superclass constructor, which in this new exception class is Run. Time. Exception 12
Client code public class See. Our. Own. Exception { public static void main(String[] args) { Song song = new Song(); if (!song. can. Play. Today()) throw new Unplayable. Song. Exception(”n. Song spent : -)"); } } Exception in thread "main" tests. Unplayable. Song. Exception: Song spent : -) at tests. See. Our. Own. Exception. main(See. Our. Own. Exception. java: 10) 13
5) java. io uses inheritance too w The Buffered. Reader class is often used with Input. Stream. Reader — Buffered. Reader has a read. Line method w Buffered. Reader is used for input from keyboard or a text file: Before Scanner in Java 5, use this: Input. Stream. Reader bytes. To. Char What type? = new Input. Stream. Reader(System. in); Buffered. Reader object. With. Readline = new Buffered. Reader(bytes. To. Char); System. out. print("Enter a number: "); String line = object. With. Readline. read. Line(); double number = Double. parse. Double(line); 14
Constructor takes a Reader parameter or any class that extends Reader w Since the Buffered. Reader constructor has a Reader parameter public Buffered. Reader(Reader — in) any class that extends Reader can be passed as an argument to the Buffered. Reader constructor • Input. Stream. Reader such as Java's System. in object – For keyboard input Object • File. Reader – for reading from a file Reader Part of Java's inheritance hierarchy. References to Input. Stream. Reader and File. Reader can be assigned to a Reader reference (one-way assignment) Buffered. Reader has. Readline = new Buffered. Reader( Input. Stream. Reader ); File. Reader 15
There are 10 “Reader” types java. io. Reader implements java. io. Closeable, java. lang. Readable java. io. Buffered. Reader java. io. Line. Number. Reader java. io. Char. Array. Reader java. io. Filter. Reader java. io. Pushback. Reader java. io. Input. Stream. Reader java. io. File. Reader java. io. Piped. Reader java. io. String. Reader 16
6) Window. Listener needs 7 methods private class Respond. To. Window. Events implements Window. Listener { @Override public void window. Activated(Window. Event e) { } @Override public void window. Closing(Window. Event e) { } @Override public void window. Deactivated(Window. Event e) { } @Override public void window. Deiconified(Window. Event e) { } @Override public void window. Iconified(Window. Event e) { } @Override public void window. Opened(Window. Event e) { } } 17
Or extend Window. Adapter w To help, you can have the Window. Listener extend Window. Adapter to save writing all 7 methods w This gives you all 7 as method stubs that do nothing w Then override Window. Closing w see next slide 18
Confirm. Message. Dialog // Assumes set. Default. Close. Operation(JFrame. DO_NOTHING_ON_CLOSE); private class Respond. To. Window. Events extends Window. Adapter { public void window. Closing(Window. Event evt) { int user. Input = JOption. Pane. show. Confirm. Dialog(null, "Save data? "); assert (user. Input == JOption. Pane. NO_OPTION // or 1 || user. Input == JOption. Pane. YES_OPTION // or 0 || user. Input == JOption. Pane. CANCEL_OPTION); // or 2 // Do whatever is appropriate for your application // You will want to terminate the program after saves System. exit(0); } } 19
7) Allows for some interesting Patterns 20
8) Useful inheritance hierarchies w As developers, we might find a group of related objects that best fit into an inheritance Hieararchy 21
Benefits of Inheritance w Oracle’s Java website claims inheritance offers the following benefits: — Subclasses provide specialized behaviors from the basis of common elements provided by the superclass. Through the use of inheritance, programmers can reuse the code in the superclass many times. — Programmers can implement superclasses called abstract classes that define "generic" behaviors. The abstract superclass defines and may partially implement the behavior, but much of the class is undefined and unimplemented. Other programmers fill in the details with specialized subclasses. 22
Purpose of Abstract Classes w Why have Abstract classes? — — Define generic behaviors Can implement the common behaviors w Summary of how to guarantee that derived classed implement certain methods — — Declare the method abstract--do not implement it Use the key word abstract in the method heading and end with ; rather than { } 23
Uses of inheritance continued w You can print any Object with to. String — — Inheritance is one feature that distinguishes the objectoriented style of programming At a minimum, because every class extends Object, every class is guaranteed to understand the to. String message. If a class does not override to. String, the to. String method in the Object class executes w Inheritance gives us polymorphic messages — Inheritance is one way to implement polymorphism (Java interfaces are the other way). Polymorphism allows the same message to be sent to different types of objects for behavior that is appropriate to the type 24
Design Principle Favor object composition over class inheritance Inheritance is a cool way to change behavior. But we know that it's brittle because the subclass can easily make assumptions about the context in which a method it overrides is getting called. … Composition has a nicer property. The coupling is reduced by just having some smaller things you plug into something bigger, and the bigger object just calls the smaller object 25
Review Inheritance public abstract class Animal. Kingdom { private String phylum; public Animal. Kingdom(String p) phylum = p; } { public String get. Phylum(){ return phylum; } public abstract void eat(); } 26
Extend it twice class Giraffe extends Animal. Kingdom { public Giraffe(String p) { super(p); } public void eat() { /*go for leaves*/ } } class Shark extends Animal. Kingdom { public Shark(String p) { super(p); } public void eat() { /*scan the beach*/ } } 27
Particularities of Abstract Classes w Cannot be instantiated w A class can be declared abstract even though it has no abstract methods w You can create variables of an abstract class —it must reference a concrete (nonabstract) subclass Animal giraffe = new Giraffe("Chordata"); Animal shark = new Shark(”Jaws"); 28
…More particularities w A subclass cannot access the private fields of its superclass — Use getters or setters if you need to access or change them or super in you constructor to initialize them w If a subclass does not implement the abstract methods of its parent, it too must be abstract w Protected methods and fields are known throughout the package — and to all subclasses even if in another package 29
Four Access Modifier Visibility private None other than the class where declared None(default) Classes in the package protected Classes in package and subclasses inside or outside the package public All classes in the project 30
Another consideration w Can not reduce visibility when overriding — Can not override a public method with a private one w However we can make it look like we can override a private method with a public one — However, since the inherited private method is not seen by the subclass, it is not really overridden 31
An abuse of Inheritance w Stack<E> extends Vector<E> Stack<Integer> s = new Stack<Integer>(); s. push(5); s. push(1); s. push(4); s. push(2); s. push(3); System. out. println(s); Collections. shuffle(s); Output (is this LIFO? ) System. out. println(s); [5, 1, 4, 2, 3] s. remove(5); [4, 2, 5, 3, 1] System. out. println(s); s. insert. Element. At(-999, 2); [4, 2, 3, 1] [4, 2, -999, 3, 1] System. out. println(s); 32
- Slides: 32