Lecture 19 Topics: Abstract Classes and Interfaces Abstract Classes Interfaces o The Comparable interface o The Cloneable Interface - optional Readings: Lecture Notes Chapter 15 A superclass defines common behavior for related subclasses. In the inheritance hierarchy, classes become more and more specific and concrete with each new subclass. An interface can be used to define common behavior for classes including unrelated classes. Abstract classes are very general. They cannot be used to create (instantiate) objects. An abstract class can contain abstract methods. These methods are implemented in subclasses. public abstract class person { } Let’s take a look at the following example: GeometricObject.java public abstract class GeometricObject { private String color = "white"; private boolean filled; private java.util.Date dateCreated; /** Construct a default geometric object */ /** Defined as protected; can only be used by subclasses */ protected GeometricObject() { dateCreated = new java.util.Date(); } /** Construct a geometric object with color and filled value */ protected GeometricObject(String color, boolean filled) { dateCreated = new java.util.Date(); this.color = color; this.filled = filled; } 1|Page //getters and setters /** Return color */ public String getColor() { return color; } /** Set a new color */ public void setColor(String color) { this.color = color; } /** Return filled. Since filled is boolean, * the get method is named isFilled */ public boolean isFilled() { return filled; } /** Set a new filled */ public void setFilled(boolean filled) { this.filled = filled; } /** Get dateCreated */ public java.util.Date getDateCreated() { return dateCreated; } /** Return a string representation of this object */ public String toString() { return "created on " + dateCreated + "\ncolor: " + color + " and filled: " + filled; } /** Abstract method getArea */ public abstract double getArea(); /** Abstract method getPerimeter */ public abstract double getPerimeter(); } The methods getArea() and getPerimeter() defined in the GeometricObject are overridden in the Circle class and the Rectangle class. 2|Page public class TestGeometricObject { /** Main method */ public static void main(String[] args) { // Declare and initialize two geometric objects GeometricObject geoObject1 = new Circle(5); GeometricObject geoObject2 = new Rectangle(5, 3); System.out.println("The two objects have the same area? " + equalArea(geoObject1, geoObject2)); // Display circle displayGeometricObject(geoObject1); // Display rectangle displayGeometricObject(geoObject2); } //end main /** A method for comparing the areas of two geometric objects */ public static boolean equalArea(GeometricObject object1, GeometricObject object2) { return object1.getArea() == object2.getArea(); } /** A method for displaying a geometric object */ public static void displayGeometricObject(GeometricObject object) { System.out.println(); System.out.println("The area is " + object.getArea()); System.out.println("The perimeter is " + object.getPerimeter()); } } When invoking equalArea(geoObject1, geoObject2) the getArea() method defined in the Circle class is used for object1.getArea() and the getArea() method defined in the Rectangle class is used for object2.getArea(). This is possible due to the fact that getArea() is declared as abstract method. In UML graphic notation the abstract methods are italicized. Abstract classes: o An Abstract class helps defining a base case for a specific set of objects. o Cannot be contained in a non-abstract class. A class that contains abstract methods must be abstract. Abstract methods can only be contained in abstract classes. o Cannot be used to create objects but it can have its own constructors invoked in the constructors of its subclasses. o Can contain a mix of concrete (implemented) methods and abstract (unimplemented) methods. An abstract class can contain no abstract methods. 3|Page o In order to create an instance of an Abstract class you must first extend it from a concrete (non abstract) class. This can be done by overriding the abstract method in the concrete class. o Extending an Abstract class from a concrete class forces the subclass to implement all abstract methods. o If a subclass extends an abstract class and does not implement all the abstract methods then it must be declared as abstract. o An abstract class can be used as a data type. Therefore the following is correct: GeometricObject[] objects = new GeometricObject[10]; You can then create an instance of GeometricObject and assign its reference to the array: objects[0] = new Circle; Choosing interfaces and abstract classes is not an either/or proposition. If you need to change your design, make it an interface. However, you may have abstract classes that provide some default behavior. Abstract classes are excellent candidates inside of application frameworks. Abstract classes let you define some behaviors; they force your subclasses to provide others. For example, if you have an application framework, an abstract class may provide default services such as event and message handling. Those services allow your application to plug in to your application framework. However, there is some application-specific functionality that only your application can perform. Such functionality might include startup and shutdown tasks, which are often application-dependent. So instead of trying to define that behavior itself, the abstract base class can declare abstract shutdown and startup methods. The base class knows that it needs those methods, but an abstract class lets your class admit that it doesn't know how to perform those actions; it only knows that it must initiate the actions. When it is time to start up, the abstract class can call the startup method. When the base class calls this method, Java calls the method defined by the subclass class. Case Study: the Abstract Number Class pp 565 We discussed wrappers a while ago. Number is an abstract superclass for numeric wrapper classes like BigInteger, BigDecimal and so on. intValue, longValue, floatValue and doubleValue cannot be implemented in the Number class since they are specific to the type of data. They are defined as abstract methods in the Number abstract class. 4|Page Interfaces The Java interface is used to share common behavior (only method headers) among the instances of different classes. Inheritance is used to share common code (including both data members and methods) among the instances of related classes. An interface is a class-like construct that contains only constants and abstract methods. An interface is used to specify common behavior for objects of (related or unrelated) classes. modifier interface InterfaceName{ //constant declarations //abstract method signature } Example: Teacher Person (abstract) name: String speak(): void sleep(): void eat():void Student Animal (abstract) name: String eat():void sleep():void play():void Jaguar Pig Pre-K Which of these classes is very messy? Let’s say one good answer might be Pre-K and Pig. Pre-K and Pig are in different abstract (unrelated) classes. How can we connect them through this common characteristic? Let’s say we have a special method named cleanAfterMe(). We do not want to have this method implemented at the level of Teacher or Jaguar, not even the Student. It can be done by creating an interface. 5|Page Person (abstract) name: String speak(): void sleep(): void eat():void Teacher Student Animal (abstract) name: String eat():void sleep():void play():void Jaguar Pig Pre-K Messy Interface cleanAfterMe():void public interface Messy{ //contains abstract methods and/or constants only public abstract void cleanAfterMe(); } We also must mention that the class will implement that interface: public class Pre-K extends Person implements Messy { ….. } public class Pig extends Animal implements Messy{ …………… } 6|Page Classes that implement an interface MUST implement all its methods in order to compile. If a superclass implements an interface, then its subclasses must implement the same interface. Interfaces can be used as a data type, allowing you to store in a common collection unrelated objects. Messy[] messyCreatures = new Messy[2]; messyCreatures[0] = new Pre-K(“nana”); messyCreatures[1] = new Pig(“peppa”); Case Study: TestEdible.java pp 570 public interface Edible { /** Describe how to eat */ public abstract String howToEat(); } public class TestEdible { public static void main(String[] args) { Object[] objects = {new Tiger(), new Chicken(), new Apple()}; for (int i = 0; i < objects.length; i++) { if (objects[i] instanceof Edible) System.out.println(((Edible)objects[i]).howToEat()); if (objects[i] instanceof Animal) { System.out.println(((Animal)objects[i]).sound()); } } } } abstract class Animal { /** Return animal sound */ public abstract String sound(); } class Chicken extends Animal implements Edible { @Override public String howToEat() { return "Chicken: Fry it"; } @Override 7|Page public String sound() { return "Chicken: cock-a-doodle-doo"; } } class Tiger extends Animal { @Override public String sound() { return "Tiger: RROOAARR"; } } abstract class Fruit implements Edible { // Data fields, constructors, and methods omitted here } class Apple extends Fruit { @Override public String howToEat() { return "Apple: Make apple cider"; } } class Orange extends Fruit { @Override public String howToEat() { return "Orange: Make orange juice"; } } The Comparable interface The comparable interface defines the compareTo() method for comparing objects. //interface for comparing objects package java.lang; public interface Comparable<E>{ public int compareTo(E o); } compareTo(): accepts a reference to another object and returns an integer. Returns +1 if the object is bigger than the one is being compared to. Returns 0 if the objects are the same. Returns -1 if the object is smaller than the one is being compared to. 8|Page public class SpongeBob implements Comparable<SpongeBob>{ } public class String extends Object implements Comparable<String>{ } @Override public int compareTo(String o){ } Numbers, Strings and dates are comparable. Not everything is comparable. Let’s say you want to compare hundreds of objects and not just two. The solution is by using the Comparable interface. If you implement the Comparable interface you can use Java’s sort built-in functionality. You cannot use java.util.Arrays.sort() to sort an array of Rectangles objects, because Rectangle does not implement Comparable. public class ComparableRectangle extends Rectangle implements Comparable<ComparableRectangle> { /** Construct a ComparableRectangle with specified properties */ public ComparableRectangle(double width, double height) { super(width, height); } @Override // Implement the compareTo method defined in Comparable public int compareTo(ComparableRectangle o) { if (getArea() > o.getArea()) return 1; else if (getArea() < o.getArea()) return -1; else return 0; } @Override // Implement the toString method in GeometricObject public String toString() { return "Width: " + getWidth() + " Height: " + getHeight() + " Area: " + getArea(); } } 9|Page ComparableRectangle extends Rectangle and implements Comparable (inherits all the constants from Comparable interface and implements the methods in the interface). compareTo method compare the area of the two rectangles. An instance of ComparableRectangle is an instance of Rectangle, GeometricObject, Object and Comparable. public class SortRectangles { public static void main(String[] args) { ComparableRectangle[] rectangles = { new ComparableRectangle(3.4, 5.4), new ComparableRectangle(13.24, 55.4), new ComparableRectangle(7.4, 35.4), new ComparableRectangle(1.4, 25.4)}; java.util.Arrays.sort(rectangles); for (Rectangle rectangle: rectangles) { System.out.print(rectangle + " "); System.out.println(); } } } Interfaces vs. Abstract Classes A class can implement multiple interfaces, but it can only extend one superclass. Java allows only single inheritance for class extension but allows multiple extensions for interfaces. Table 15.2 Variables Constructors Methods Abstract Class No restrictions. No restrictions. Interface All variables must be Are invoked by subclasses. No constructors. An interface cannot be instantiated using the new operator public static final All must be public abstract instance methods. 10 | P a g e The Cloneable Interface specifies that an object can be cloned. package java.lang; public interface Cloneable{ } The objects can be cloned using the clone() method defined in the Object class. Many classes in the Java library implement Cloneable. You can clone an array using the clone method: int[] list1 = {1,2}; int [] list2 = list1.clone(); list1[0]=7; list2[1]=8; list1 list 2 1,2 1,2 list1 list2 7,2 1,8 List 1 is 7,2 List 2 is 1,8 How to implement Cloneable The class must override the clone() method in the Object class. Case study: House.java implements Cloneable and Comparable. public class House implements Cloneable, Comparable <House> { private int id; private double area; private java.util.Date whenBuilt; public House(int id, double area) { this.id = id; this.area = area; whenBuilt = new java.util.Date(); } public double getId() { return id; } public double getArea() { return area; 11 | P a g e } public java.util.Date getWhenBuilt() { return whenBuilt; } /** Override the protected clone method defined in the Object class, and strengthen its accessibility */ @override public Object clone() throws CloneNotSupportedException { return super.clone(); } /** Implement the compareTo method defined in Comparable */ @override public int compareTo(Object o) { if (area > ((House)o).area) return 1; else if (area < ((House)o).area) return -1; else return 0; } } You can create an object of the House class and create an identical copy from it: House house1 = new House(1 , 1750); House house2 = (House) house1.clone(); The clone method copies each field from the original object to the target object. If the field is of primitive type its value is copied. If the field is of an object, the reference of the field is copied. The object’s reference type is copied rather than its content: shallow copy. NOTE: An interface can extend other interfaces but not classes. A class can extend its superclass and implement multiple interfaces. 12 | P a g e