570 likes | 777 Views
Interfaces, Polymorphism, and Inheritance. Sections 8.4, 8.1. Outcomes. Create a polymorphic function for Lists and other interfaces Recognize, write, and implement interfaces Use inheritance to add methods to an existing class Override inherited methods such as toString and equals.
E N D
Interfaces, Polymorphism, and Inheritance Sections 8.4, 8.1
Outcomes • Create a polymorphic function for Lists • and other interfaces • Recognize, write, and implement interfaces • Use inheritance to add methods to an existing class • Override inherited methods such as toString and equals
Similar Classes • Separate classes can have similar actions • ArrayList & LinkedList • add an item, remove an item, ask if empty, get an item from a given position, … • But they are completely different data types • can’t use an ArrayList method on a LinkedList • but the LinkedList version of that method would have exactly the same code in the body
ArrayListvs. LinkedList • Only difference is “Array” “Linked” • and that’s only in the header! • the bodies are exactly the same p.v.printArrayList(ArrayList<String> l) {Sopln(“List is:”);for (String s : l)Sopln(“\t” + s);Sopln(); } p.v.printLinkedList(LinkedList<String> l) {Sopln(“List is:”);for (String s : l)Sopln(“\t” + s);Sopln(); } See SillyDuplication.java
Calling AL/LL Methods • Arguments must match parameters ArrayList<String> al = new ArrayList<String>(); LinkedList<String> ll = new LinkedList<String>(); … printArrayList(al); // OK printLinkedList(ll); // OK printArrayList(ll); // NOT OK printLinkedList(al); // NOT OK • errors: • required ArrayList, found LinkedList • required LinkedList, found ArrayList
“List” Actions • ArrayList & LinkedList have same methods • add(_), remove(_), isEmpty(), get(_), … • also listIterator() • All these methods are “List” actions • things we want to do with a list • It’d be nice if we could write one method to deal with both kinds of lists • turns out we can!
Polymorphic printList Method • One method that works for both types public void printList(List<String> l) { System.out.println(“List is:”); for (String s : l) { System.out.println(“\t” + s); } System.out.println(); } • called “polymorphic” (= many shapes) • Works because Java knows what Lists do See ListsAreLists.java
Calling List Methods • Both kinds match List parameters ArrayList<String> al = new ArrayList<String>(); LinkedList<String> ll = new LinkedList<String>(); … printList(al); // OK printList(ll); // OK • no errors! • printList is expecting to be given a List • ArrayListsare Lists • LinkedListsare Lists
Polymorphic Variables • Parameters are variables • we can have List variables other places, too List<String> al = new ArrayList<String>(); List<String> ll = new LinkedList<String>(); … printList(al); // OK printList(ll); // OK • But! No such thing as a List object List<String> al = new List<String>(); java.util.list is abstract; cannot be instantiated
What is java.util.List • It’s what’s called an interface • a list of public methods without bodies • It’s a list of things an object could do • but doesn’t say how it would do them • Every List has certain methods defined • add(_), remove(_), get(_), listIterator(), … • but each kind of List does them its own way • ArrayList one way; LinkedList another way googlejava List to see what methods a List must have
Why Use Interfaces? • We can say what needs doing without saying how it needs to be done • because we mostly don’t care how it’s done • (e.g.) We need a class we can use as a list • this class says it can be used as a list, so let’s use it • Don’t get stuck with one class • make an interface & let anyone implement it • use new & better classes as they come along • (it’s much easier to add new things) See StringList.java
Interface Declaration public interface InterfaceName{ Public_Constant_Declarations… Public_Method_Headers… } • Very much like a class definition • interface instead of class • methods all public • none of them have bodies! • public constants allowed, too
Interface • Tell Java that group of actions goes together • name the group of actions • say what the actions are • do not say how to do them • different kinds of things may do them different ways public interface Measurable { public double getArea(); public double getPerimeter(); } See Measurable.java
Using an Interface • Tell method to expect a Measurable object • can use any Measurable method for that object • getArea or getPerimeter public double roundness(Measurable m) { return 4 * Math.PI * m.getArea() / Math.pow(m.getPerimeter(), 2); } • cannot use any other methods! (*) • we don’t know what other methods it might have (*) not exactly true, but pretty close! See MeasuringStuff.java
Using Measurable Objects • Suppose Circle is Measurable Circle c = new Circle(10.0); System.out.println(“Roundness of c is ” + roundness(c)); • c has getArea and getPerimeter methods… • because Circles are Measurables • …so method works just fine • similarly for Rectangles Rectangle r = new Rectangle(10.0, 20.0); System.out.println(“Roundness of r is ” + roundness(r)); Roundness of c is 1.0 Roundness of r is 0.6981317007977318
Making Classes Measurable • Need to know that a class is Measurable • it’s not enuf to just have the methods • need to tell Java that we have the methods • Done in the class declaration • an implements clause (compare: throws clause) public class Circle implements Measurable { … } public class Rectangle implements Measurable { … } • tells Java they have getArea & getPerimeter • don’t lie! Java will catch you out
The Circle Implementation public class Circle implements Measurable { private double radius; public Circle(double r) { radius = r; } public double getRadius() { return radius; } public double getCircumference() { return 2 * Math.PI * radius; } public double getDiameter() { return 2 * radius; } public double getArea() { return Math.PI * Math.pow(radius, 2); } public double getPerimeter () { return getCircumference(); } } • says it implements Measurable, then does • has other methods, too – but that’s OK See Circle.java
The Rectangle Implementation public class Rectangle implements Measurable { private double length, width; public Rectangle(double l, double w) { length = l; width = w; } public double getLength() { return length; } public double getWidth() { return width; } public double getArea() { return length * width; } public double getPerimeter () { return 2 * (length + width); } } • says it implements Measurable, then does • the implementations are different than for Circles See Rectangle.java
Exercise • Declare an interface named Playable that has the following methods: • void play() • void play(intnumTimes) • double playLength()
Exercise • Write a Square class that implements the Measurable interface • it has an edgeLength (double) • area is edgeLength squared • perimeter is four times edgeLength
Non-Interface Methods • Class may have methods that are not part of the interface • Rectangle: getHeight & getWidth • Circle: getRadius & getCircumference • Polymorphic parameters/variables cannot use those methods • can only use interface methods
What’s OK? • Methods you can ask for depend on the variable, not the object Circle c = new Circle(10); c.getPerimeter(); c.getArea(); c.getRadius(); c.getCircumference(); Rectangle r = new Rectangle(10, 20); r.getPerimeter(); r.getArea(); r.getHeight(); r.getWidth(); Measurable m = new Circle(10); m.getPerimeter(); m.getArea(); m.getRadius(); m.getCircumference();
Compile-Time Method Checking • Try to make sure program won’t crash • make it as safe as we can (no guarantees!) • Asking a Rectangle for its radius would cause a crash • Measurable could be a Rectangle • Asking a Measurable for its radius could cause a crash
Run-Time Method Selection • Anything we ask a Measurable to do... • ...will be part of the interface • because our compile-time checking made sure • The Measurable object knows how to do it • because of compile-time checking of class • Object uses its own version of the method • known as late (or dynamic) binding In C++, early (static) binding chooses a version of the method at compile time.
Variables & Types • Measurable variable is polymorphic • can hold a Circle or Rectangle object • can assign from a different type variable Measurable m; Circle c = new Circle(10); Rectangle r = new Rectangle(10, 20); m = c; m = r; Compare storing an int variable into a double variable: int n = 5; double x = n;
Variables & Types • Cannot go the other way around Measurable m = new Circle(10); Rectangle r; Circle c; r = m; c = m; • doesn’t like either of those Compare storing a double variable into an int variable: double x = 5.0; int n = x;
Type Casting • Can tell Java you want to do it anyway! • tell Java to treat the Measurable as a Circle Measurable m = new Circle(10); Circle c; c = (Circle) m; • will crash if object is wrong type Rectangle r; r = (Rectangle) m; Crash Contrast casting a double variable into an int variable: double x = 5.5; int n = (int)x;
Checking the Type • Can ask if an object is a given type • hey, m, are you are Circle? if (m instanceof Circle) { Circle c = (Circle) m; double radius = c.getRadius(); • Still can’t ask it to do non-Measurable stuff if (m instanceof Circle) System.out.print(m.getRadius()); Note: all lower-case letters!
Implementing Multiple Interfaces • Can implement more than one interface • list interfaces, separated by commas public class MultiPurpose implements InterA, InterB {...} public class Yikes implements IA, IB, IC, IDa, IDb {...} • Must define every method from every interface it implements • no lying!
Extending Interfaces • Consider this interface: public interface Polygonal { public double getArea(); public double getPerimeter(); public intgetNumberOfSides(); } • has all Measurable’s methods, plus one more • Can simplify the definition: public interface Polygonal extends Measurable { public intgetNumberOfSides(); } See Polygonal.java
Implementing Polygonal • Anything that implements Polygonal must define all the methods mentioned in Polygonal interface... public intgetNumberOfSides() • ...plus all those mentioned in Measurable public double getArea() public double getPerimeter()
And So On... • Can extend an interface that extends another • just adding more methods to implement public interface RegularPolygonal extends Polygonal {...} • Can extend more than one interface • again, adding more methods to implement public interface FiniteSurfaceextends Measurable, Colourable { ... } Measurable Colourable Polygonal FiniteSurface RegularPolygonal See them!
Combining Interfaces • When one interface extends two others... • (or more than two others) • ...it may not need any more methods • it just puts those two (or more) interfaces together • use empty braces (no new methods required) public interface FiniteSurface extends Measureable, Colourable {}
Exercise • What methods must these classes implement? public interface IA {public void is();} public interface IB {public inthowMany();} public interface IC extends IB {public String whatKind();} public interface ID extends IA, IC {} public interface IE extends IA, IB {public void what();} public class A implements IE {...} public class B implements ID {...} public class C implements IA, IB {...}
Interface Summary • An interface is a data type • variables can have that data type • including (especially) parameters for methods • such variables (methods) called polymorphic • An interface lists public methods • each implementing class implements them • each class has its own implementation • these classes are similar kinds of things • Circles and Rectangles are similar kinds of things
Sharing Method Definitions • Each class has its own implementation • each class may implement it a different way • But what if some methods are implemented the same way for every class? • e.g. every Person’s getName method is same • whether Student, Faculty, Staff, or Administration (all those classes have Person methods) • it’d be nice if we could share implementations • and we can!
Using Another Class’s Methods • Easiest way to share methods • take all of another class’s methods • One class implements lots of methods • ArrayList<String>, say • Another class says “I do all that and more” • extends the other class public class StringListInheritedextendsArrayList<String> { … } • StringList does everything ArrayList<String> does, the same way it does See StringListInherited.java
Parent and Child; Super and Sub • Class with extends clause (MyStringClass) is called a child class or a subclass • Class it extends (ArrayList<String>) is called a parent class or a superclass • Child inherits all parent’s public methods • don’t even need to say what they are • doesn’t inherit anything private!
Inheritance public class Parent { private String value; public void setValue(String v) { this.value = v; } public String getValue() { return this.value; } } public class Child extends Parent { public void sayValue() { System.out.println(“My value is ” + this.getValue()); } } Child c = new Child(); c.setValue(“Fred”); c.sayValue(); Each Child object has a getValue method and a setValue method, even tho’ it didn’t (explicitly) say it did! My value is Fred
Non-Inheritance public class Parent { private String value; public void setValue(String v) { this.value = v; } public String getValue() { return this.value; } } public class Child extends Parent { public void sayValue() { System.out.println(“My value is ” + value); } } Even tho’ each Child object has a value, it’s not allowed to talk about it! It’s private to the Parent class!
Why Use Inheritance • Same reasons as for interfaces • Better than interfaces in some ways • saves work of implementing common methods • Worse than interfaces in other ways • less flexible (single inheritance) • comes with baggage • Which to use? • depends on exact circumstances
Exercise • Create a new class SortableStringList that does everything an ArrayList does, but also allows you to ask the list to sort itself. SortableStringListssl = new SortableStringList(); ssl.add(“Ten”); ssl.add(“Twenty”); ssl.add(“Thirty”); ssl.sort(); System.out.println(“ssl sorted is ” + ssl); • Hint: it’s not as hard as it might sound! ssl sorted is [Ten, Thirty, Twenty]
Changed Methods • Child gets every public method from Parent but doesn’t have to stick with it! • child can change the method’s implementation • just say what the new implementation is • this is called over-riding the inherited definition public class Child extends Parent { public void sayValue() { Sopln(“My value is ” + this.getValue()); } public String getValue() { return “Ba-ba”;} } Child c = new Child(); c.setValue(“Fred”); c.sayValue(); My value is Ba-ba
Over-Riding Methods • Still inherits the changed method • use super.methodName to get inherited version • compare this.methodName public class Child extends Parent { public void sayValue() { Sopln(“My value is ” + this.getValue()); } public String getValue() { return super.getValue().replace(‘r’,’w’); } } • super.getValue is Parent’s version of getValue • it returns “Fred” • replace(‘r’,’w’) changes that to “Fwed” Child c = new Child(); c.setValue(“Fred”); c.sayValue(); My value is Fwed
Inheritance and Polymorphism • If a method asks for a Parent object… public static void printValue(Parent p) { … } • …a Child object will do Child c = new Child(); printValue(c); • Just like interfaces • Child has all the methods Parent has • so Child can do anything Parent can • so Child can replace Parent anywhere
Inheritance and Polymorphism • If a method asks for a Child object… public static void doThis(Child p) { … } • …a Parent object will not do Parent p = new Parent(); doThis(p); • Child has all the methods Parent has • Parent may not have all the methods Child does • so Parent cannot replace Parent anywhere
More Inheritance • You can extend a class that extends another • Parent Child Grandchild • and so on! • Child inherits all Parent’s public methods • Grandchild inherits all Child’s public methods • including the ones it inherited from Parent • But Java allows only one parent class • this is called “single inheritance” • C++ allows “multiple inheritance” = many parents
Inheritance Hierarchies • Java uses inheritance (and interfaces) lots • for example, ArrayList: • java.util • Class ArrayList<E> • java.lang.Object • java.util.AbstractCollection<E> • java.util.AbstractList<E> • java.util.ArrayList<E> • All Implemented Interfaces: Serializable, Cloneable, Iterable<E>, Collection<E>, List<E>, RandomAccessDirect Known Subclasses: AttributeList, RoleList, RoleUnresolvedList ArrayList extends AbstractList extends AbstractCollection extends Object implements Serializable, Cloneable, Iterable, Collection, List, RandomAccess
The Object Class • There is a class in Java called Object • If a class has no extends clause… • …then it extends Object • So every class extends Object • is a child, grandchild, great-grandchild, … • Every class inherits Object’s methods • including its definitions • but remember, you can over-ride the definition
Object Methods • Has 11, but we’re most concerned with: • equals(Object o) – am I equals to o? • toString() – this is how I should be printed. • Object definitions: • equals(Object o): same as == • toString() – “Class@hashcode” • print/println automatically uses toString(): Circle c = new Circle(5.2); Sopln(c); Circle@9304b1