Presentation is loading. Please wait.

Presentation is loading. Please wait.

Abstract classes, Interfaces

Similar presentations


Presentation on theme: "Abstract classes, Interfaces"— Presentation transcript:

1 Abstract classes, Interfaces
Recitation 4 Abstract classes, Interfaces

2 A Little More Geometry! Shape x ____ y ____ Square area() size ____
Abstract Classes A Little More Geometry! Shape x ____ y ____ Square area() size ____ Triangle area() base____ height ____ Circle area() radius ____ Encourage the students to download the code for this online The goal is to incorporate an area method for all shapes x,y are coordinates that are for all shapes. Each subclass has its own relevant fields. Explain that Circle, Square, and Triangle all have different area() methods but Shape does not have one

3 Demo 1: Complete this function
Abstract Classes Demo 1: Complete this function /** Return the sum of the areas of * the shapes in s */ static double sumAreas(Shape[] s) { } Operator instanceof and casting are required Adding new Shape subclasses breaks sumAreas Show them the code and how each of the subclasses have an area method but not in superclass Shape Point out how ugly the casting makes the function private static double sumAreas(Shape[] shapes){ int total = 0; for (int i = 0; i < shapes.length; i++) { if (shapes[i] instanceof Square) { total += ((Square) shapes[i]).area(); } else if (shapes[i] instanceof Triangle) { total += ((Triangle) shapes[i]).area(); } else if (shapes[i] instanceof Circle) { total += ((Circle) shapes[i]).area(); } return total; Discussion notes regarding the function: Not very extensible: if you try to add another subclass All methods using Shapes need to change Bugs appear if more subclasses are added and methods aren’t fixed Casting is ugly, verbose, and has potential for runtime errors Also! All different types of shapes have area, but superclass Shape doesn’t have an area method - a bit strange

4 A Partial Solution: Add method area to class Shape:
Abstract Classes A Partial Solution: Add method area to class Shape: public double area() { return 0; } public double area() { throw new RuntimeException(“area not overridden”); } Let’s try to solve the casting problem: Ask for ideas. Solve our earlier problem - makes sumAreas(..) simple and clean, but has its own host of issues: Subclasses of Shape have to remember to override - easy to lose track of, cause bugs down the line Shapes that aren’t subclasses have 0 area, which would normally be incorrect Now add the RuntimeException: Gets even closer. Now we can’t call getArea on Shapes that aren’t subclasses. Still, Subclasses of Shape have to remember to override - easy to lose track of, cause bugs down the line Makes a lot more Runtime Errors - Compile Time are easier to catch and fix

5 Problems not solved Shape s = new Shape(...); Should be disallowed
Abstract Classes Problems not solved What is a Shape that isn’t a Circle, Square, Triangle, etc? What is only a shape, nothing more specific? Shape s = new Shape(...); Should be disallowed 2. What if a subclass doesn’t override area()? Can’t force the subclass to override it! Incorrect value returned or exception thrown.

6 Solution: Abstract classes
public abstract class Shape { public double area() { return 0; } Abstract class Can’t be instantiated. (new Shape() illegal) This solves our first problem - by making Shape abstract, we don’t have to worry about instantiating it. Cannot create an object of class Shape because use of new-expression is illegal. So every Shape is truly a Circle, Square, Triangle, or some other subclass.

7 Solution: Abstract methods
Abstract Classes Solution: Abstract methods public abstract class Shape { public abstract double area(); } Can have implemented methods, too Place abstract method only in abstract class. Semicolon instead of body. Abstract method Subclass must override. This solves the second problem. An abstract method must be overridden in every subclass - not doing so is a compile time error --program us illegal. An abstract method doesn’t have a body - just method header then semicolon.

8 Demo 2: A better solution
Abstract Classes Demo 2: A better solution We modify class Shape to be abstract and make area() an abstract method. Abstract class prevents instantiation of class Shape Abstract method forces all subclasses to override area() Make Shape abstract, the problem of area() is now solved Go back and make the first demo look a lot cleaner. Note: You don’t have to go over those bullet points, the next slide handles them for emphasis. import java.util.Arrays; public abstract class Shape implements Comparable<Shape> { private int x; private int y; /** Constructor: a shape with bounding box top left (x, y). */ public Shape(int x, int y) { this.x= x; this.y= y; } /** = area of this Shape. */ public abstract double area(); /** = < 0, 0, or > 0 depending on whether this Shape's * area is smaller, than, equal to, or grater than s's area*/ int compareTo(Shape s) { double diff= area() - s.area(); return (diff == 0 ? 0 : diff < 0 ? -1 : +1); /** = repr of this Shape, giving its position. */ public String toString() { return "(" + x + ", " + y + ")"; /** Method main to test things. */ public static void main(String[] args) { Shape[] shapes= new Shape[5]; shapes[0]= new Circle(3, 4, 2); shapes[1]= new Circle(1, 2, 15); shapes[2]= new Square(0, 0, 20); shapes[3]= new Square(0, 0, 5); shapes[4]= new Square(0, 0, 2); System.out.println("unsorted: " + Arrays.toString(shapes)); Arrays.sort(shapes); System.out.println(" sorted: " + Arrays.toString(shapes));

9 Abstract Classes, Abstract Methods
Cannot instantiate an object of an abstract class. (Cannot use new-expression) A subclass must override abstract methods. Why? Java requires this so that the following doesn’t happen. If subclasses didn’t override the abstract method, we could have a situation where the method gets called but it has no implementation to use If we could instantiate an object of an abstract class and tried to call one of the abstract methods, it would have no implementation to use

10 Interfaces

11 Problem Where is the best place to implement whistle()? Animal Mammal
Interfaces Problem Where is the best place to implement whistle()? Animal Mammal Bird Whistler Human Dog Parrot If we were to implement a method whistle(), where is the best place to implement whistle? Some of our animals like Human and Parrot should be able to whistle but Dog should not. Two problems: We could implement whistle() in a superclass, but that doesn’t really make sense because not all animals, mammals, or birds are whistlers. We could implement whistle() in just Human and Parrot, but then we would have to do that ugly casting again in order to run whistle(). It would be great to have a second class Whistler that we could extend! Human could just inherit from Whistler and Mammal.

12 No multiple inheritance in Java!
Interfaces No multiple inheritance in Java! class Whistler { void breathe() { … } } class Animal { class Human extends Animal, Whistler { new Human().breathe(); Which breathe() should java run in class Human? Can extend only one class! Java does not allow this because it doesn’t know which method breathe to call. C++ has always had multiple inheritance and it’s always been a problem.

13 Why not make it fully abstract?
Interfaces Why not make it fully abstract? class abstract Whistler { abstract void breathe(); } class abstract Animal { class Human extends Animal, Whistler { Java doesn’t allow this, even though it would work. Instead, Java has another construct for this purpose, the interface Use abstract classes instead? Seems okay because method bodies are not given. But Java does not allow this, because abstract classes can still have similarly named non-abstract methods. Instead, Java has a construct, the interface, which is like an abstract class but has more restrictions.

14 Solution: Interfaces public interface Whistler { void whistle();
int MEANING_OF_LIFE= 42; } class Human extends Mammal implements Whistler { methods are automatically public and abstract fields are automatically public, static, and final (i.e. constants) Must implement all methods in the implemented interfaces An interface is like a fully abstract class but has a slightly different syntax. An interface can contain type signatures for methods, just like abstract methods in abstract classes, but they have to be public. An interface can contain fields, but they have to be public, static, and final and they have to contain an initializer. So they are really just constants

15 Multiple interfaces public interface Singer { void singTo(Human h); }
class Human extends Mammal implements Whistler, Singer { Classes can implement several interfaces! They must implement all the methods in those interfaces they implement. Must implement singTo(Human h) and whistle() NOTE If someone asks about conflicting constants in interfaces, Java will actually have an compile-time error due to ambiguity. So you would need to call the constant you want from the interface like Whistler.MEANING_OF_LIFE or Singer.MEANING_OF_LIFE. Similarly for conflicting return types for methods of the same name, java will say that the return type is incompatible with one of the interfaces.

16 Interfaces Solution: Interfaces Interface Whistler offers promised functionality to classes Human and Parrot! Animal Mammal Bird Whistler Human Dog Parrot Implementing an interface allows a class to become more formal about the behavior it promises to provide. Interfaces form a contract between the class and the outside world, and this contract is enforced at build time by the compiler. If your class claims to implement an interface, the class will compile only if all methods defined by that interface are overridden in the class ---are declared in the class.

17 Casting to an interface
Interfaces Casting to an interface Human h = new Human(); Object o = (Object) h; Animal a = (Animal) h; Mammal m = (Mammal) h; Singer s = (Singer) h; Whistler w = (Whistler) h; All point to the same memory address! Object Animal Whistler Mammal Singer Human There are six (compiler) perspectives of the same Human object. From each perspective, you can call a method m() (say) only if it is defined in that perspective or above it; otherwise, the call is illegal. This ensures that a method to be called actually exists at runtime. But of course the object does NOT change when one casts.

18 Casting to an interface
Interfaces Casting to an interface Human h = new Human(); Object o = h; Animal a = h; Mammal m = h; Singer s = h; Whistler w = h; Object Automatic up-cast Animal Whistler Mammal Singer Forced down-cast Human Note that explicit upcasts are unnecessary. Explicit downcasts are necessary --and they should be done only if it is KNOWN that the cast will work (use instanceof to check that). Note that c instanceof C is true iff c has a partition called C. For the object shown on this slide, h instance of C is true for C being Whistler, Human, Mammal, Singer, Animal, and Object.

19 Casting up to an interface automatically
Interfaces Casting up to an interface automatically class Human … implements Whistler { void listenTo(Whistler w) {...} } Human h = new Human(...); Human h1= new Human(...); h.listenTo(h1); Object Animal Whistler Mammal Arg h1 of the call has type Human. Its value is being stored in w, which is of type Whistler. Java does an upward cast automatically. It costs no time; it is just a matter of perception. Human When h.listenTo(h) or h.listenTo(w) gets called, it calls the listenTo method declared in Human. (“Bottom-up rule”) w.listenTo(w) doesn’t compile because a Whistler object does not have a listenTo method. Whenever we call upon w, the compiler knows that it can call upon the methods that were declared in (the type) Whistler.

20 Demo 3: Implement Comparable<T>
Implement interface Comparable in class Shape: public interface Comparable<T> { /** = a negative integer if this object < c, = 0 if this object = c, = a positive integer if this object > c. Throw a ClassCastException if c cannot be cast to the class of this object. */ int compareTo(T c); } In class Shape, we can write method compareTo that orders Shapes based on their areas. For example, if Shape object s1 has a smaller area than Shape object s2, s1.compareTo(s2) should return a negative number. class Shape implements Comparable<Shape> { public int compareTo(Shape s) { double diff= area() - s.area(); if (diff < 0) { return -1; } else if (diff == 0) { return 0; } else { return 1; }

21 Shape implements Comparable<T>
public class Shape implements Comparable<Shape> { ... /** … */ public int compareTo(Shape s) { double diff= area() - s.area(); return (diff == 0 ? 0 : (diff < 0 ? -1 : +1)); } At this point, in your Demo, change class Shape to implement Comparable<T> as shown on this slide, adding method compareTo and implementing Comparable<Shape>. You should then be able to run method main and show them that the sort works. Note: It would be nice to write compareTo using just: return area() - s.area() but the expression is a double. And if we try to cast it to an int, using return (int)(area() - s.area()); it doesn’t give the right answer is the area different is between -1 and 1 (non-inclusive).

22 Beauty of interfaces Boolean Byte Double Integer
Arrays.sort sorts an array of any class C, as long as C implements interface Comparable<T> without needing to know any implementation details of the class. Classes that implement Comparable: Boolean Byte Double Integer String BigDecimal BigInteger Calendar Time Timestamp and 100 others Beauty of interfaces All 110 very diverse/different classes that implement Comparable just need to use one method! (Arrays.sort) Interfaces stop us from needlessly writing 110 different sort implementations! If YOUR class C (say) implements Comparable, thus providing a method that gives an ordering to objects of the class, you can use Arrays.sort to sort arrays C[].

23 String sorting Arrays.sort(Object[] b) sorts an array of any class C, as long as C implements interface Comparable<T>. String implements Comparable, so you can write String[] strings= ...; ... Arrays.sort(strings); During the sorting, when comparing elements, a String’s compareTo function is used Because of interfaces, we need only one sort method, which just relies on compareTo. As long as Arrays.sort can cast elements to type Comparable, it can reliably call method compareTo.

24 And Shape sorting, too! Arrays.sort(Object[] b) sorts an array of any class C, as long as C implements interface Comparable<T>. Shape implements Comparable, so you can write Shape[] shapes= ...; ... Arrays.sort(shapes); During the sorting, when comparing elements, a Shape’s compareTo function is used Because of interfaces, we need only one sort method, which just relies on compareTo. As long as Arrays.sort can cast elements to type Comparable, it can reliably call method compareTo.

25 Abstract Classes vs. Interfaces
Abstract class represents something Sharing common code between subclasses Interface is what something can do A contract to fulfill Software Engineering purpose Similarities: Can’t instantiate Must implement abstract methods Later we’ll use interfaces to define “abstract data types” (e.g. List, Set, Stack, Queue, etc) (If you have time) go through the points in the context of the previous examples of Humans/whistlers and shapes. Software Engineering: specify and enforce boundaries between different parts of a team project Because they will have had some exposure to Lists, you can say that if they implement the List<T> interface, it allows a user to have a guarantee that their list implementation will have those List methods. It doesn’t say anything about the implementation (backing array vs. objects and pointers). It just needs to satisfy the specification. Else, there will be a compiler error.


Download ppt "Abstract classes, Interfaces"

Similar presentations


Ads by Google