Presentation is loading. Please wait.

Presentation is loading. Please wait.

Interfaces.

Similar presentations


Presentation on theme: "Interfaces."— Presentation transcript:

1 Interfaces

2 Interfaces in its most common form, a Java interface is a declaration (but not an implementation) of an API in its most common form, an interface is made up of public abstract methods an abstract method is a method that has an API but does not have an implementation consider an interface for mathematical functions of the form 𝑦=𝑓(𝑥)

3 semicolon, and no method body
import java.util.List; public interface Function { /** * Evaluate the function at x. * x the value at which to evaluate the function the value of the function evaluated at x */ public double eval(double x); * Evaluate the function at each value of x in the given list. x a list of values at which to evaluate the function the list of values of the function evaluated at the given * values of x public List<Double> eval(List<Double> x); } semicolon, and no method body semicolon, and no method body

4 Interfaces notice that the interface declares which methods exist and specifies the contract of the methods but it does not specify how the methods are implemented the method implementations are defined by classes that implement the interface consider the functions: 𝑦= 𝑥 2 𝑦= 1 𝑥 𝑦= 4 𝜋 𝑛=1,3,5… 𝑛 𝑚𝑎𝑥 sin 𝑛𝜋𝑥 𝑛

5 Square implements the Function interface
public class Square implements Function public double eval(double x) { return x * x; } public List<Double> eval(List<Double> x) { List<Double> result = new ArrayList<>(); for (Double val : x) { result.add(this.eval(val)); return result; // no constructors because Square has no fields Square must provide an implementation of eval(double) Square must provide an implementation of eval(List<Double>)

6 Reciprocal implements the Function interface
public class Reciprocal implements Function public double eval(double x) { return 1.0 / x; } public List<Double> eval(List<Double> x) { List<Double> result = new ArrayList<>(); for (Double val : x) { result.add(this.eval(val)); return result; // no constructors because Reciprocal has no fields Reciprocal must provide an implementation of eval(double) Reciprocal must provide an implementation of eval(List<Double>)

7 SquareWave implements the Function interface
public class SquareWave implements Function { private int nmax; public SquareWave(int nmax) { if (nmax < 1) { throw new IllegalArgumentException(); } this.nmax = public double eval(double x) { double result = 0; for (int n = 1; n < this.nmax; n += 2) { result += Math.sin(n * Math.PI * x) / n; return 4 / Math.PI * result; SquareWave must provide an implementation of eval(double)

8 SquareWave must provide an implementation of eval(List<Double>)
@Override public List<Double> eval(List<Double> x) { List<Double> result = new ArrayList<>(); for (Double val : x) { result.add(this.eval(val)); } return result; SquareWave must provide an implementation of eval(List<Double>)

9 SquareWave SquareWave implements the Fourier series for a square wave
results for nmax = 101

10 Interfaces in the Java library
interfaces are widely used in the Java library Collection, List, Set, Map Iterable, Iterator CharSequence , Appendable Comparable

11 Interfaces are types an interface is a reference data type
if you define a reference variable whose type is an interface, any object you assign to it must be an instance of a class that implements the interface ( List<String> t = new ArrayList<String>(); interface implements the interface

12 Interfaces are types an interface is a reference data type
if you define a reference variable whose type is an interface, any object you assign to it must be an instance of a class that implements the interface ( Function f = new SquareWave(101); interface implements the interface

13 Inheritance Notes Chapter 6

14 Inheritance you know a lot about an object by knowing its class
for example what is a Komondor?

15 Object Dog Dog is-a Object PureBreed is-a Dog PureBreed is-a Object PureBreed Mix Komondor is-a PureBreed Komondor is-a Dog Komondor is-a Object BloodHound Komondor ...

16 Object Dog PureBreed Mix BloodHound Komondor ...
superclass of Dog (and all other classes) Object superclass == base class parent class subclass == derived class extended class child class subclass of Object superclass of PureBreed Dog subclass of Dog superclass of Komondor PureBreed Mix BloodHound Komondor ...

17 Object Dog Dog extends Object PureBreed Mix PureBreed extends Dog BloodHound Komondor ... Komondor extends PureBreed

18 Some Definitions we say that a subclass is derived from its superclass
with the exception of Object, every class in Java has one and only one superclass Java only supports single inheritance a class X can be derived from a class that is derived from a class, and so on, all the way back to Object X is said to be descended from all of the classes in the inheritance chain going back to Object all of the classes X is derived from are called ancestors of X

19 Why Inheritance? a subclass inherits all of the non-private members (fields and methods but not constructors) from its superclass if there is an existing class that provides some of the functionality you need you can derive a new class from the existing class the new class has direct access to the public and protected attributes and methods without having to re- declare or re-implement them the new class can introduce new fields and methods the new class can re-define (override) its superclass methods

20 Is-A inheritance models the is-a relationship between classes
is-a means is-substitutable-for

21 Is-A from a Java point of view, is-a means you can use a derived class instance in place of an ancestor class instance public SomeClass { public someMethod(Dog dog) { // does something with dog } // client code of someMethod Komondor shaggy = new Komondor(); SomeClass.someMethod( shaggy ); // OK, Komondor is-a dog Mix mutt = new Mix (); SomeClass.someMethod( mutt ); // OK, Mix is-a dog

22 Is-A Pitfalls is-a has nothing to do with the real world
is-a has everything to do with how the implementer has modelled the inheritance hierarchy the classic example: Circle is-a Ellipse? Ellipse Circle

23 Circle is-a Ellipse? mathematically a circle is a kind of ellipse
but if Ellipse can do something that Circle cannot, then Circle is-a Ellipse is false for the purposes of inheritance remember: is-a means you can substitute a derived class instance for one of its ancestor instances if Circle cannot do something that Ellipse can do then you cannot (safely) substitute a Circle instance for an Ellipse instance

24 // method in Ellipse /. Change the width and height of the ellipse
// method in Ellipse /* * Change the width and height of the ellipse. width the desired width. height the desired height. width > 0 && height > 0 */ public void setSize(double width, double height) { this.width = width; this.height = height; }

25 can't Circle override setSize so that it sets width == height?
there is no good way for Circle to support setSize (assuming that the fields width and height are always the same for a Circle) because clients expect setSize to set both the width and height can't Circle override setSize so that it throws an exception if width != height? no; this will surprise clients because Ellipse.setSize does not throw an exception if width != height can't Circle override setSize so that it sets width == height? no; this will surprise clients because Ellipse.setSize says that the width and height can be different

26 what if there is no setSize method?
if a Circle can do everything an Ellipse can do then Circle can extend Ellipse

27 A Naïve Inheritance Example
a stack is an important data structure in computer science data structure: an organization of information for better algorithm efficiency or conceptual unity e.g., list, set, map, array widely used in computer science and computer engineering e.g., undo/redo can be implemented using two stacks

28 Stack examples of stacks

29 Top of Stack top of the stack

30 Stack Operations classically, stacks only support two operations
push add to the top of the stack pop remove from the top of the stack there is no way to access elements of the stack except at the top of the stack

31 Push st.push("A") st.push("B") st.push("C") st.push("D") st.push("E")
top "E" top "D" top "C" top "B" top "A"

32 Pop String s = st.pop() s = st.pop() top "E" top "D" top "C" top "B"
"A"

33 Implementing stack using inheritance
a stack looks a lot like a list pushing an element onto the top of the stack looks like adding an element to the end of a list popping an element from the top of a stack looks like removing an element from the end of the list if we have stack inherit from list, our stack class inherits the add and remove methods from list we don't have to implement them ourselves let's try making a stack of integers by inheriting from ArrayList<Integer>

34 Implementing stack using inheritance
import java.util.ArrayList; public class BadStack extends ArrayList<Integer> { } use the keyword extends followed by the name of the class that you want to extend

35 Implementing stack using inheritance
import java.util.ArrayList; public class BadStack extends ArrayList<Integer> { public void push(int value) { this.add(value); } public int pop() { int last = this.remove(this.size() - 1); return last; push = add to end of this list pop = remove from end of this list

36 Implementing stack using inheritance
that's it, we’re done! public static void main(String[] args) { BadStack t = new BadStack(); t.push(0); t.push(1); t.push(2); System.out.println(t); System.out.println("pop: " + t.pop()); } [0, 1, 2] pop: 2 pop: 1 pop: 0

37 Implementing stack using inheritance
why is this a poor implementation? by having BadStack inherit from ArrayList<Integer> we are saying that a stack is a list anything a list can do, a stack can also do, such as: get a element from the middle of the stack (instead of only from the top of the stack) set an element in the middle of the stack iterate over the elements of the stack

38 Implementing stack using inheritance
public static void main(String[] args) { BadStack t = new BadStack(); t.push(100); t.push(200); t.push(300); System.out.println("get(1)?: " + t.get(1)); t.set(1, -1000); System.out.println("set(1, -1000)?: " + t); } [100, 200, 300] get(1)?: 200 set(1, -1000)?: [100, -1000, 300]

39 Implementing stack using inheritance
using inheritance to implement a stack is an example of an incorrect usage of inheritance inheritance should only be used when an is-a relationship exists a stack is not a list, therefore, we should not use inheritance to implement a stack even experts sometimes get this wrong early versions of the Java class library provided a stack class that inherited from a list-like class java.util.Stack

40 Other ways to implement stack
use composition Stack has-a List the end of the list is the top of the stack push adds an element to the end of the list pop removes the element at the end of the list

41 Inheritance (Part 2) Notes Chapter 6

42 Object Dog Dog extends Object PureBreed Mix PureBreed extends Dog BloodHound Komondor ... Komondor extends PureBreed

43 Implementing Inheritance
suppose you want to implement an inheritance hierarchy that represents breeds of dogs for the purpose of helping people decide what kind of dog would be appropriate for them many possible fields: appearance, size, energy, grooming requirements, amount of exercise needed, protectiveness, compatibility with children, etc. we will assume two fields measured on a 10 point scale size from 1 (small) to 10 (giant) energy from 1 (lazy) to 10 (high energy)

44 Dog public class Dog extends Object { private int size; private int energy; // creates an "average" dog Dog() { this(5, 5); } Dog(int size, int energy) { this.setSize(size); this.setEnergy(energy); }

45 public int getSize() { return this
public int getSize() { return this.size; } public int getEnergy() { return this.energy; } public final void setSize(int size) { this.size = size; } public final void setEnergy(int energy) { this.energy = energy; } } why final? stay tuned…

46 What is a Subclass? a subclass looks like a new class that has the same API as its superclass with perhaps some additional methods and fields the new class has direct access to the public and protected* fields and methods without having to re- declare or re-implement them the new class can introduce new fields and methods the new class can re-define (override) its superclass methods * the notes does not discuss protected access

47 Mix UML Diagram a mixed breed dog is a dog whose ancestry is unknown or includes more than one pure breed Dog 1 Mix ArrayList<String> breeds

48 Dog - size : int - energy : int + setSize() + setEnergy() + equals(Object) : boolean + hashCode() : int + toString() : String ... Mix - breeds : ArrayList<String> + getBreeds() : List<String> + equals(Object) : boolean + hashCode() : int + toString() : String ... subclass can add new fields subclass can add new methods subclass can change the implementation of inherited methods

49 What is a Subclass? a subclass looks like a new class that has the same API as its superclass with perhaps some additional methods and fields inheritance does more than copy the API of the superclass the derived class contains a subobject of the parent class the superclass subobject needs to be constructed (just like a regular object) the mechanism to perform the construction of the superclass subobject is to call the superclass constructor

50 What is a Subclass? another model of inheritance is to imagine that the subclass contains all of the fields of the parent class (including the private fields), but cannot directly use the private fields

51 Mix Memory Diagram 500 Mix object size 1 energy 10 breeds 1000a
size and energy belong to the superclass private in superclass not accessible by name to Mix

52 Constructors of Subclasses
the purpose of a constructor is to set the values of the fields of this object how can a constructor set the value of a field that belongs to the superclass and is private? by calling the superclass constructor and passing this as an implicit argument

53 Constructors of Subclasses
the first line in the body of every constructor must be a call to another constructor if it is not then Java will insert a call to the superclass default constructor if the superclass default constructor does not exist or is private then a compilation error occurs a call to another constructor can only occur on the first line in the body of a constructor the superclass constructor must be called during construction of the derived class

54 Mix (version 1) public final class Mix extends Dog { // no declaration of size or energy; part of Dog private ArrayList<String> breeds; public Mix () { // call to a Dog constructor super(); this.breeds = new ArrayList<String>(); } public Mix(int size, int energy) { super(size, energy);

55 public Mix(int size, int energy, ArrayList<String> breeds) { // call to a Dog constructor super(size, energy); this.breeds = new ArrayList<String>(breeds); }

56 Mix (version 2 using chaining)
public final class Mix extends Dog { // no declaration of size or energy; part of Dog private ArrayList<String> breeds; public Mix () { // call to a Mix constructor this(5, 5); } public Mix(int size, int energy) { this(size, energy, new ArrayList<String>());

57 public Mix(int size, int energy, ArrayList<String> breeds) { // call to a Dog constructor super(size, energy); this.breeds = new ArrayList<String>(breeds); }

58 why is the constructor call to the superclass needed?
because Mix is-a Dog and the Dog part of Mix needs to be constructed

59 Mix mutt = new Mix(1, 10); Mix object Dog object Mix constructor starts running creates new Dog subobject by invoking the Dog constructor Dog constructor starts running creates new Object subobject by (silently) invoking the Object constructor Object constructor runs and finishes sets size and energy creates a new empty ArrayList and assigns it to breeds Object object size 1 energy 10 breeds 1000

60 ArrayList<String> object
Mix Memory Diagram 500 Mix object size 1 energy 10 breeds 1000a 1000 ArrayList<String> object ...

61 Invoking the Superclass Ctor
why is the constructor call to the superclass needed? because Mix is-a Dog and the Dog part of Mix needs to be constructed similarly, the Object part of Dog needs to be constructed

62 Invoking the Superclass Ctor
a derived class can only call its own constructors or the constructors of its immediate superclass Mix can call Mix constructors or Dog constructors Mix cannot call the Object constructor Object is not the immediate superclass of Mix Mix cannot call PureBreed constructors cannot call constructors across the inheritance hierarchy PureBreed cannot call Komondor constructors cannot call subclass constructors

63 Constructors & Overridable Methods
if a class is intended to be extended then its constructor must not call an overridable method Java does not enforce this guideline why? recall that a derived class object has inside of it an object of the superclass the superclass object is always constructed first, then the subclass constructor completes construction of the subclass object the superclass constructor will call the overridden version of the method (the subclass version) even though the subclass object has not yet been constructed

64 Superclass Ctor & Overridable Method
public class SuperDuper { public SuperDuper() { // call to an over-ridable method; bad this.overrideMe(); } public void overrideMe() { System.out.println("SuperDuper overrideMe");

65 Subclass Overrides Method
public class SubbyDubby extends SuperDuper { private final Date date; public SubbyDubby() { super(); this.date = new Date(); public void overrideMe() { System.out.println("SubbyDubby overrideMe : " + this.date); public static void main(String[] args) { SubbyDubby sub = new SubbyDubby(); sub.overrideMe();

66 the programmer's intent was probably to have the program print:
SuperDuper overrideMe SubbyDubby overrideMe : <the date> or, if the call to the overridden method was intentional but the program prints: SubbyDubby overrideMe : null final attribute in two different states!

67 What's Going On? new SubbyDubby() calls the SubbyDubby constructor
the SubbyDubby constructor calls the SuperDuper constructor the SuperDuper constructor calls the method overrideMe which is overridden by SubbyDubby the SubbyDubby version of overrideMe prints the SubbyDubby date field which has not yet been assigned to by the SubbyDubby constructor (so date is null) the SubbyDubby constructor assigns date SubbyDubby overrideMe is called by the client

68 remember to make sure that your base class constructors only call final methods or private methods
if a base class constructor calls an overridden method, the method will run in an unconstructed derived class

69 Preconditions and Inheritance
what the method assumes to be true about the arguments passed to it inheritance (is-a) a subclass is supposed to be able to do everything its superclasses can do how do they interact?

70 Preconditions and Inheritance
a subclass can change a precondition on a method but whatever argument values the superclass method accepts must also be accepted by the subclass method

71 Strength of a Precondition
to strengthen a precondition means to make the precondition more restrictive // Dog setEnergy // 1. no precondition // 2. 1 <= energy // 3. 1 <= energy <= 10 // 4. energy == 5 public void setEnergy(int energy) { ... } weakest precondition strongest precondition

72 Preconditions on Overridden Methods
a subclass can change a precondition on a method but it must not strengthen the precondition a subclass that strengthens a precondition is saying that it cannot do everything its superclass can do // Dog setEnergy // assume non-final none public void setEnergy(int nrg) { // ... } // Mix setEnergy // bad : strengthen precond. 1 <= nrg <= 10 public void setEnergy(int nrg) { if (nrg < 1 || nrg > 10) { // throws exception } // ... }

73 client code written for Dogs now fails when given a Mix
remember: a subclass must be able to do everything its ancestor classes can do; otherwise, clients will be (unpleasantly) surprised // client code that sets a Dog's energy to zero public void walk(Dog d) { d.setEnergy(0); }

74 Postconditions and Inheritance
what the method promises to be true when it returns the method might promise something about its return value "returns size where size is between 1 and 10 inclusive" the method might promise something about the state of the object used to call the method "sets the size of the dog to the specified size" the method might promise something about one of its parameters how do postconditions and inheritance interact?

75 Postconditions and Inheritance
a subclass can change a postcondition on a method but whatever the superclass method promises will be true when it returns must also be true when the subclass method returns

76 Strength of a Postcondition
to strengthen a postcondition means to make the postcondition more restrictive // Dog getSize // 1. no postcondition // 2. return value >= 1 // 3. return value // between 1 and 10 // 4. return 5 public int getSize() { ... } weakest postcondition strongest postcondition

77 Postconditions on Overridden Methods
a subclass can change a postcondition on a method but it must not weaken the postcondition a subclass that weakens a postcondition is saying that it cannot do everything its superclass can do // Dog getSize // 1 <= size <= 10 public int getSize() { // ... } // Dogzilla getSize // bad : weaken postcond. 1 <= size public int getSize() { // ... } Dogzilla: a made-up breed of dog that has no upper limit on its size

78 client code written for Dogs can now fail when given a Dogzilla
remember: a subclass must be able to do everything its ancestor classes can do; otherwise, clients will be (unpleasantly) surprised // client code that assumes Dog size <= 10 public String sizeToString(Dog d) { int sz = d.getSize(); String result = ""; if (sz < 4) result = "small"; else if (sz < 7) result = "medium"; else if (sz <= 10) result = "large"; return result; }

79 IllegalArgumentException
Exceptions all exceptions are objects that are subclasses of java.lang.Throwable Throwable Exception RuntimeException ... ... and many, many more IllegalArgumentException ... ... and many more AJ chapter 9

80 User Defined Exceptions
you can define your own exception hierarchy often, you will subclass Exception Exception public class DogException extends Exception DogException BadSizeException NoFoodException BadDogException

81 Exceptions and Inheritance
a method that claims to throw a checked exception of type X is allowed to throw any checked exception type that is a subclass of X this makes sense because exceptions are objects and subclass objects are substitutable for ancestor classes // in Dog public void someDogMethod() throws DogException { // can throw a DogException, BadSizeException, // NoFoodException, or BadDogException }

82 a method that overrides a superclass method that claims to throw a checked exception of type X can also claim to throw a checked exception of type X or a subclass of X remember: a subclass is substitutable for the parent type // in Mix @Override public void someDogMethod() throws DogException { // ... }

83 Inheritance (cont) Abstract Classes

84 Polymorphism inheritance allows you to define a base class that has fields and methods classes derived from the base class can use the public and protected base class fields and methods polymorphism allows the implementer to change the behaviour of the derived class methods

85 CockerSpaniel toString Mix toString
// client code public void print(Dog d) { System.out.println( d.toString() ); } // later on... Dog fido = new Dog(); CockerSpaniel lady = new CockerSpaniel(); Mix mutt = new Mix(); this.print(fido); this.print(lady); this.print(mutt); Dog toString CockerSpaniel toString Mix toString

86 notice that fido, lady, and mutt were declared as Dog, CockerSpaniel, and Mutt
what if we change the declared type of fido, lady, and mutt ?

87 CockerSpaniel toString Mix toString
// client code public void print(Dog d) { System.out.println( d.toString() ); } // later on... Dog fido = new Dog(); Dog lady = new CockerSpaniel(); Dog mutt = new Mix(); this.print(fido); this.print(lady); this.print(mutt); Dog toString CockerSpaniel toString Mix toString

88 what if we change the print method parameter type to Object ?

89 CockerSpaniel toString Mix toString Date toString
// client code public void print(Object obj) { System.out.println( obj.toString() ); } // later on... Dog fido = new Dog(); Dog lady = new CockerSpaniel(); Dog mutt = new Mix(); this.print(fido); this.print(lady); this.print(mutt); this.print(new Date()); Dog toString CockerSpaniel toString Mix toString Date toString

90 obj.toString() Late Binding
polymorphism requires late binding of the method name to the method definition late binding means that the method definition is determined at run-time non-static method obj.toString() run-time type of the instance obj

91 Declared vs Run-time type
Dog lady = new CockerSpaniel(); declared type run-time or actual type

92 Dog lady = new CockerSpaniel();
the declared type of an instance determines what methods can be used the name lady can only be used to call methods in Dog lady.someCockerSpanielMethod() won't compile Dog lady = new CockerSpaniel();

93 Dynamic dispatch Dog lady = new CockerSpaniel();
the actual type of the instance determines what definition is used when the method is called lady.toString() uses the CockerSpaniel definition of toString selecting which version of a polymorphic method to use at run-time is called dynamic dispatch Dog lady = new CockerSpaniel();

94 Abstract classes

95 Abstract Classes sometimes you will find that you want the API for a base class to have a method that the base class cannot define e.g. you might want to know what a Dog's bark sounds like but the sound of the bark depends on the breed of the dog you want to add the method bark to Dog but only the subclasses of Dog can implement bark

96 Abstract Classes sometimes you will find that you want the API for a base class to have a method that the base class cannot define e.g. you might want to know the breed of a Dog but only the subclasses have information about the breed you want to add the method getBreed to Dog but only the subclasses of Dog can implement getBreed

97 in Java an abstract class is a class that you cannot make instances of
if the base class has methods that only subclasses can define and the base class has fields common to all subclasses then the base class should be abstract if you have a base class that just has methods that it cannot implement then you probably want an interface abstract : (dictionary definition) existing only in the mind in Java an abstract class is a class that you cannot make instances of e.g.

98 an abstract class provides a partial definition of a class
the "partial definition" contains everything that is common to all of the subclasses the subclasses complete the definition an abstract class can define fields and methods subclasses inherit these an abstract class can define constructors subclasses must call these an abstract class can declare abstract methods subclasses must define these (unless the subclass is also abstract)

99 Abstract Methods an abstract base class can declare, but not define, zero or more abstract methods the base class is saying "all Dogs can provide a String describing the breed, but only the subclasses know enough to implement the method" public abstract class Dog { // fields, ctors, regular methods public abstract String getBreed(); }

100 Abstract Methods the non-abstract subclasses must provide definitions for all abstract methods consider getBreed in Mix

101 public class Mix extends Dog { // stuff from before
public class Mix extends Dog { // stuff from public String getBreed() { if(this.breeds.isEmpty()) { return "mix of unknown breeds"; } StringBuffer b = new StringBuffer(); b.append("mix of"); for(String breed : this.breeds) { b.append(" " + breed); } return b.toString();

102 PureBreed a purebreed dog is a dog with a single breed
one String field to store the breed note that the breed is determined by the subclasses the class PureBreed cannot give the breed field a value but it can implement the method getBreed the class PureBreed defines an field common to all subclasses and it needs the subclass to inform it of the actual breed PureBreed is also an abstract class

103 public abstract class PureBreed extends Dog { private String breed; public PureBreed(String breed) { super(); this.breed = breed; } public PureBreed(String breed, int size, int energy) { super(size, energy);

104 @Override public String getBreed() { return this.breed; }

105 Subclasses of PureBreed
the subclasses of PureBreed are responsible for setting the breed consider Komondor

106 Komondor public class Komondor extends PureBreed { private final String BREED = "komondor"; public Komondor() { super(BREED); } public Komondor(int size, int energy) { super(BREED, size, energy); // other Komondor methods...

107 Another example: Tetris
played with 7 standard blocks called tetriminoes blocks drop from the top player can move blocks left, right, and down player can spin blocks left and right

108 Tetriminoes spinning the I, J, and S blocks

109 Tetriminoes features common to all tetriminoes
has-a color has-a shape has-a position draw move left, right, and down features unique to each kind of tetrimino the actual shape spin left and right

110 class name in italics for abstract classes
a 2D point a grid object that stores the shape protected constructor Block - color : Color - position : Point2 - grid : BlockGrid # Block(int, Point2, Color) + draw() + moveDown() + moveLeft() + moveRight() ... Block is abstract because we can't define the shape of a generic block IBlock + IBlock(Point2, Color) + spinLeft() + spinRight() constructor defines the shape methods modify the shape to produce the rotated version of the block

111 Inheritance (cont) Static Features

112 Static Fields and Inheritance
static fields behave the same as non-static fields in inheritance public and protected static fields are inherited by subclasses, and subclasses can access them directly by name private static fields are not inherited and cannot be accessed directly by name but they can be accessed/modified using public and protected methods

113 Static Fields and Inheritance
the important thing to remember about static fields and inheritance there is only one copy of the static field shared among the declaring class and all subclasses consider trying to count the number of Dog objects created by using a static counter

114 // the wrong way to count the number of Dogs created public abstract class Dog { // other fields... static protected int numCreated = 0; Dog() { // ... Dog.numCreated++; } public static int getNumberCreated() { return Dog.numCreated; // other contructors, methods... protected, not private, so that subclasses can modify it directly

115 // the wrong way to count the number of Dogs created public class Mix extends Dog { // fields... Mix() super(); Mix.numCreated++; } // other contructors, methods...

116 // too many dogs! public class TooManyDogs { public static void main(String[] args) Mix mutt = new Mix(); System.out.println( Mix.getNumberCreated() ); } prints 2

117 What Went Wrong? there is only one copy of the static field shared among the declaring class and all subclasses Dog declared the static field Dog increments the counter every time its constructor is called Mix inherits and shares the single copy of the field Mix constructor correctly calls the superclass constructor which causes numCreated to be incremented by Dog Mix constructor then incorrectly increments the counter

118 Counting Dogs and Mixes
suppose you want to count the number of Dog instances and the number of Mix instances Mix must also declare a static field to hold the count somewhat confusingly, Mix can give the counter the same name as the counter declared by Dog

119 public class Mix extends Dog { // other fields
public class Mix extends Dog { // other fields... private static int numCreated = 0; // bad style; hides Dog.numCreated public Mix() super(); // will increment Dog.numCreated // other Mix stuff... numCreated++; // will increment Mix.numCreated } // ...

120 Hiding Fields note that the Mix field numCreated has the same name as an field declared in a superclass whenever numCreated is used in Mix, it is the Mix version of the field that is used if a subclass declares an field with the same name as a superclass field, we say that the subclass field hides the superclass field considered bad style because it can make code hard to read and understand should change numCreated to numMixCreated in Mix

121 Static Methods and Inheritance
there is a significant difference between calling a static method and calling a non-static method when dealing with inheritance there is no dynamic dispatch on static methods therefore, you cannot override a static method

122 notice no @Override notice no @Override
public abstract class Dog { private static int numCreated = 0; public static int getNumCreated() { return Dog.numCreated; } public class Mix { private static int numMixCreated = 0; return Mix.numMixCreated; public class Komondor { private static int numKomondorCreated = 0; return Komondor.numKomondorCreated; notice notice

123 public class WrongCount { public static void main(String[] args) { Dog mutt = new Mix(); Dog shaggy = new Komondor(); System.out.println( mutt.getNumCreated() ); System.out.println( shaggy.getNumCreated() ); System.out.println( Mix.getNumCreated() ); System.out.println( Komondor.getNumCreated() ); } prints 2 2 1 Dog version Dog version Mix version Komondor version

124 What's Going On? there is no dynamic dispatch on static methods
because the declared type of mutt is Dog, it is the Dog version of getNumCreated that is called because the declared type of shaggy is Dog, it is the Dog version of getNumCreated that is called

125 Hiding Methods notice that Mix.getNumCreated and Komondor.getNumCreated work as expected if a subclass declares a static method with the same name as a superclass static method, we say that the subclass static method hides the superclass static method you cannot override a static method, you can only hide it hiding static methods is considered bad form because it makes code hard to read and understand

126 the client code in WrongCount illustrates two cases of bad style, one by the client and one by the implementer of the Dog hierarchy the client should not have used an instance to call a static method the implementer should not have hidden the static method in Dog

127 Using superclass methods

128 Other Methods methods in a subclass will often need or want to call methods in the immediate superclass a new method in the subclass can call any public or protected method in the superclass without using any special syntax a subclass can override a public or protected method in the superclass by declaring a method that has the same signature as the one in the superclass a subclass method that overrides a superclass method can call the overridden superclass method using the super keyword

129 Dog equals we will assume that two Dogs are equal if their size and energy are the same @Override public boolean equals(Object obj) { boolean eq = false; if(obj != null && this.getClass() == obj.getClass()) Dog other = (Dog) obj; eq = this.getSize() == other.getSize() && this.getEnergy() == other.getEnergy(); } return eq;

130 Mix equals (version 1) two Mix instances are equal if their Dog subobjects are equal and they have the same breeds @Override public boolean equals(Object obj) { // the hard way boolean eq = false; if(obj != null && this.getClass() == obj.getClass()) { Mix other = (Mix) obj; eq = this.getSize() == other.getSize() && this.getEnergy() == other.getEnergy() && this.breeds.size() == other.breeds.size() && this.breeds.containsAll(other.breeds); } return eq; subclass can call public method of the superclass

131 Mix equals (version 2) two Mix instances are equal if their Dog subobjects are equal and they have the same breeds Dog equals already tests if two Dog instances are equal Mix equals can call Dog equals to test if the Dog subobjects are equal, and then test if the breeds are equal also notice that Dog equals already checks that the Object argument is not null and that the classes are the same Mix equals does not have to do these checks again

132 @Override public boolean equals(Object obj) { boolean eq = false; if (super.equals(obj)) { // the Dog subobjects are equal Mix other = (Mix) obj; eq = this.breeds.size() == other.breeds.size() && this.breeds.containsAll(other.breeds); } return eq; subclass method that overrides a superclass method can call the original superclass method

133 Dog toString @Override public String toString() { String s = "size " + this.getSize() + "energy " + this.getEnergy(); return s; }

134 Mix toString @Override public String toString() { StringBuffer b = new StringBuffer(); b.append(super.toString()); for(String s : this.breeds) b.append(" " + s); b.append(" mix"); return b.toString(); } size and energy of the dog breeds of the mix

135 Dog hashCode // similar to code generated by public int hashCode() { final int prime = 31; int result = 1; result = prime * result + this.getEnergy(); result = prime * result + this.getSize(); return result; } use this.energy and this.size to compute the hash code

136 Mix hashCode // similar to code generated by public int hashCode() { final int prime = 31; int result = super.hashCode(); result = prime * result + this.breeds.hashCode(); return result; } use this.energy, this.size, and this.breeds to compute the hash code

137 Graphical User Interfaces
notes Chap 7

138 Java Swing Swing is a Java toolkit for building graphical user interfaces (GUIs) old version of the Java tutorial had a visual guide of Swing components tutorial/components.html

139 JFrame window with border, title, buttons
Simple Applications simple applications often consist of just a single window (containing some controls) JFrame window with border, title, buttons

140 Simple Applications simple applications can be implemented as a subclass of a JFrame hundreds of inherited methods but only a dozen or so are commonly called by the implementer (see URL below) Object Component user interface item Container holds other components Window plain window Frame window with title and border JFrame View

141 Simple Applications a simple application made up of a: JFrame
has-a JMenuBar has-a Container (called the content pane) has-a JLabel

142 Simple Applications a simple application made up of a: JFrame
has-a JMenuBar has-a Container (called the content pane) has-a JLabel

143 Creating JFrames Create the frame
Choose what happens when the frame closes Create components and put them in the frame Size the frame Show it

144 public class ImageViewer extends JFrame implements ActionListener { // a unique identifier to associate with the Open command public static final String OPEN_COMMAND = "Open"; // a label to show the image private JLabel img; public ImageViewer() { // 1. Create the frame super("Image Viewer"); // 2. Choose what happens when the frame closes this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // 3. Create components and put them in the frame this.makeMenu(); this.makeLabel(); this.setLayout(new FlowLayout()); // 4. Size the frame this.setMinimumSize(new Dimension(600, 400)); this.pack(); // 5. Show it this.setVisible(true); }

145 public class ImageViewer extends JFrame implements ActionListener { // a unique identifier to associate with the Open command public static final String OPEN_COMMAND = "Open"; // a label to show the image private JLabel img; public ImageViewer() { // 1. Create the frame super("Image Viewer"); // 2. Choose what happens when the frame closes this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // 3. Create components and put them in the frame this.makeMenu(); this.makeLabel(); this.setLayout(new FlowLayout()); // 4. Size the frame this.setMinimumSize(new Dimension(600, 400)); this.pack(); // 5. Show it this.setVisible(true); }

146 public class ImageViewer extends JFrame implements ActionListener { // a unique identifier to associate with the Open command public static final String OPEN_COMMAND = "Open"; // a label to show the image private JLabel img; public ImageViewer() { // 1. Create the frame super("Image Viewer"); // 2. Choose what happens when the frame closes this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // 3. Create components and put them in the frame this.makeMenu(); this.makeLabel(); this.setLayout(new FlowLayout()); // 4. Size the frame this.setMinimumSize(new Dimension(600, 400)); this.pack(); // 5. Show it this.setVisible(true); }

147 controls how the components re-size and re-position when the
public class ImageViewer extends JFrame implements ActionListener { // a unique identifier to associate with the Open command public static final String OPEN_COMMAND = "Open"; // a label to show the image private JLabel img; public ImageViewer() { // 1. Create the frame super("Image Viewer"); // 2. Choose what happens when the frame closes this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // 3. Create components and put them in the frame this.makeMenu(); this.makeLabel(); this.setLayout(new FlowLayout()); // 4. Size the frame this.setMinimumSize(new Dimension(600, 400)); this.pack(); // 5. Show it this.setVisible(true); } to respond to the user selecting the Open command from the menu controls how the components re-size and re-position when the JFrame changes size

148 sizes the JFrame so that all components
public class ImageViewer extends JFrame implements ActionListener { // a unique identifier to associate with the Open command public static final String OPEN_COMMAND = "Open"; // a label to show the image private JLabel img; public ImageViewer() { // 1. Create the frame super("Image Viewer"); // 2. Choose what happens when the frame closes this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // 3. Create components and put them in the frame this.makeMenu(); this.makeLabel(); this.setLayout(new FlowLayout()); // 4. Size the frame this.setMinimumSize(new Dimension(600, 400)); this.pack(); // 5. Show it this.setVisible(true); } sizes the JFrame so that all components have their preferred size; uses the layout manager to help adjust component sizes

149 public class ImageViewer extends JFrame implements ActionListener { // a unique identifier to associate with the Open command public static final String OPEN_COMMAND = "Open"; // a label to show the image private JLabel img; public ImageViewer() { // 1. Create the frame super("Image Viewer"); // 2. Choose what happens when the frame closes this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // 3. Create components and put them in the frame this.makeMenu(); this.makeLabel(); this.setLayout(new FlowLayout()); // 4. Size the frame this.setMinimumSize(new Dimension(600, 400)); this.pack(); // 5. Show it this.setVisible(true); }

150 Labels a label displays unselectable text and images label label
JLabel label JLabel

151 private void makeLabel() { this. img = new JLabel(""); this
private void makeLabel() { this.img = new JLabel(""); this.getContentPane().add(this.img); }

152 Menus a menu appears in a menu bar (or a popup menu)
each item in the menu is a menu item menu JMenu menu bar JMenuBar menu item JMenuItem * * JMenuBar + add(JMenu) JMenu + add(JMenuItem) JMenuItem

153 Menus to create a menu create a JMenuBar
create one or more JMenu objects add the JMenu objects to the JMenuBar create one or more JMenuItem objectes add the JMenuItem objects to the JMenu

154 private void makeMenu() { JMenuBar menuBar = new JMenuBar(); JMenu fileMenu = new JMenu("File"); menuBar.add(fileMenu); JMenuItem openMenuItem = new JMenuItem("Open..."); openMenuItem.setActionCommand(ImageViewer.OPEN_COMMAND); openMenuItem.addActionListener(this); fileMenu.add(openMenuItem); this.setJMenuBar(menuBar); }

155 private void makeMenu() { JMenuBar menuBar = new JMenuBar(); JMenu fileMenu = new JMenu("File"); menuBar.add(fileMenu); JMenuItem openMenuItem = new JMenuItem("Open..."); openMenuItem.setActionCommand(ImageViewer.OPEN_COMMAND); openMenuItem.addActionListener(this); fileMenu.add(openMenuItem); this.setJMenuBar(menuBar); }

156 to respond to the user selecting the Open command from the menu
private void makeMenu() { JMenuBar menuBar = new JMenuBar(); JMenu fileMenu = new JMenu("File"); menuBar.add(fileMenu); JMenuItem openMenuItem = new JMenuItem("Open..."); openMenuItem.setActionCommand(ImageViewer.OPEN_COMMAND); openMenuItem.addActionListener(this); fileMenu.add(openMenuItem); this.setJMenuBar(menuBar); } to respond to the user selecting the Open command from the menu

157 private void makeMenu() { JMenuBar menuBar = new JMenuBar(); JMenu fileMenu = new JMenu("File"); menuBar.add(fileMenu); JMenuItem openMenuItem = new JMenuItem("Open..."); openMenuItem.setActionCommand(ImageViewer.OPEN_COMMAND); openMenuItem.addActionListener(this); fileMenu.add(openMenuItem); this.setJMenuBar(menuBar); }

158 Event Driven Programming
so far we have a frame with some UI elements (menu, menu item, label) now we need to implement the actions each UI element is a source of events button pressed, slider moved, text changed, etc. when the user interacts with a UI element an event is triggered this causes an event object to be sent to every object listening for that particular event the event object carries information about the event the event listeners respond to the event

159 Not a UML Diagram event listener A event listener B event object 1
source 1 event listener C event object 2 event source 2 event listener D

160 Implementation each JMenuItem has two inherited methods from AbstractButton public void addActionListener(ActionListener l) public void setActionCommand(String actionCommand) for the JMenuItem call addActionListener with the listener as the argument call setActionCommand with a string describing what event has occurred

161 Implementation our application has one event thiat is fired by a button (JMenuItem) a button fires an ActionEvent event whenever it is clicked ImageViewer listens for fired ActionEvents how? by implementing the ActionListener interface public interface ActionListener { void actionPerformed(ActionEvent e); }

162 @Override public void actionPerformed(ActionEvent e) { String command = e.getActionCommand(); if (command.equals(ImageViewer.OPEN_COMMAND)) { JFileChooser chooser = new JFileChooser(); int result = chooser.showOpenDialog(this); if (result == JFileChooser.APPROVE_OPTION) { String fileName = chooser.getSelectedFile().getAbsolutePath(); ImageIcon icon = new ImageIcon(fileName); if (icon.getImageLoadStatus() == MediaTracker.COMPLETE) { this.img.setIcon(icon); this.pack(); }

163 to respond to the user selecting the Open command from the menu
@Override public void actionPerformed(ActionEvent e) { String command = e.getActionCommand(); if (command.equals(ImageViewer.OPEN_COMMAND)) { JFileChooser chooser = new JFileChooser(); int result = chooser.showOpenDialog(this); if (result == JFileChooser.APPROVE_OPTION) { String fileName = chooser.getSelectedFile().getAbsolutePath(); ImageIcon icon = new ImageIcon(fileName); if (icon.getImageLoadStatus() == MediaTracker.COMPLETE) { this.img.setIcon(icon); this.pack(); } to respond to the user selecting the Open command from the menu

164 used to pick the file to open
@Override public void actionPerformed(ActionEvent e) { String command = e.getActionCommand(); if (command.equals(ImageViewer.OPEN_COMMAND)) { JFileChooser chooser = new JFileChooser(); int result = chooser.showOpenDialog(this); if (result == JFileChooser.APPROVE_OPTION) { String fileName = chooser.getSelectedFile().getAbsolutePath(); ImageIcon icon = new ImageIcon(fileName); if (icon.getImageLoadStatus() == MediaTracker.COMPLETE) { this.img.setIcon(icon); this.pack(); } used to pick the file to open

165 show the file chooser and get the user result (ok or cancel)
@Override public void actionPerformed(ActionEvent e) { String command = e.getActionCommand(); if (command.equals(ImageViewer.OPEN_COMMAND)) { JFileChooser chooser = new JFileChooser(); int result = chooser.showOpenDialog(this); if (result == JFileChooser.APPROVE_OPTION) { String fileName = chooser.getSelectedFile().getAbsolutePath(); ImageIcon icon = new ImageIcon(fileName); if (icon.getImageLoadStatus() == MediaTracker.COMPLETE) { this.img.setIcon(icon); this.pack(); } show the file chooser and get the user result (ok or cancel)

166 user picked a file and pressed ok
@Override public void actionPerformed(ActionEvent e) { String command = e.getActionCommand(); if (command.equals(ImageViewer.OPEN_COMMAND)) { JFileChooser chooser = new JFileChooser(); int result = chooser.showOpenDialog(this); if (result == JFileChooser.APPROVE_OPTION) { String fileName = chooser.getSelectedFile().getAbsolutePath(); ImageIcon icon = new ImageIcon(fileName); if (icon.getImageLoadStatus() == MediaTracker.COMPLETE) { this.img.setIcon(icon); this.pack(); } user picked a file and pressed ok

167 directory path that the user picked
@Override public void actionPerformed(ActionEvent e) { String command = e.getActionCommand(); if (command.equals(ImageViewer.OPEN_COMMAND)) { JFileChooser chooser = new JFileChooser(); int result = chooser.showOpenDialog(this); if (result == JFileChooser.APPROVE_OPTION) { String fileName = chooser.getSelectedFile().getAbsolutePath(); ImageIcon icon = new ImageIcon(fileName); if (icon.getImageLoadStatus() == MediaTracker.COMPLETE) { this.img.setIcon(icon); this.pack(); } get the file name and directory path that the user picked

168 @Override public void actionPerformed(ActionEvent e) { String command = e.getActionCommand(); if (command.equals(ImageViewer.OPEN_COMMAND)) { JFileChooser chooser = new JFileChooser(); int result = chooser.showOpenDialog(this); if (result == JFileChooser.APPROVE_OPTION) { String fileName = chooser.getSelectedFile().getAbsolutePath(); ImageIcon icon = new ImageIcon(fileName); if (icon.getImageLoadStatus() == MediaTracker.COMPLETE) { this.img.setIcon(icon); this.pack(); } try to read the image

169 successfully read from disk
@Override public void actionPerformed(ActionEvent e) { String command = e.getActionCommand(); if (command.equals(ImageViewer.OPEN_COMMAND)) { JFileChooser chooser = new JFileChooser(); int result = chooser.showOpenDialog(this); if (result == JFileChooser.APPROVE_OPTION) { String fileName = chooser.getSelectedFile().getAbsolutePath(); ImageIcon icon = new ImageIcon(fileName); if (icon.getImageLoadStatus() == MediaTracker.COMPLETE) { this.img.setIcon(icon); this.pack(); } if the image was successfully read from disk

170 set the label image and re-size the frame
@Override public void actionPerformed(ActionEvent e) { String command = e.getActionCommand(); if (command.equals(ImageViewer.OPEN_COMMAND)) { JFileChooser chooser = new JFileChooser(); int result = chooser.showOpenDialog(this); if (result == JFileChooser.APPROVE_OPTION) { String fileName = chooser.getSelectedFile().getAbsolutePath(); ImageIcon icon = new ImageIcon(fileName); if (icon.getImageLoadStatus() == MediaTracker.COMPLETE) { this.img.setIcon(icon); this.pack(); } set the label image and re-size the frame

171 public static void main(String[] args) { // make an ImageViewer instance new ImageViewer(); }


Download ppt "Interfaces."

Similar presentations


Ads by Google