Interfaces, Polymorphism, and Inheritance
570 likes | 793 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.
Interfaces, Polymorphism, and Inheritance
E N D
Presentation Transcript
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