/* Lab 5, Part 1 - Abstraction Make sure you are in the ProfessorJ Intermediate language level. This lab introduces the use of abstract classes. Abstract classes can be considered a mix of interfaces and normal classes. Like interfaces, abstract classes define similarities between unions of classes, but can not be directly instantiated. However, unlike interfaces, abstract classes can contain fields and concrete methods (methods with bodies). Interfaces define a contract that all classes of that type must conform to, in the form of method headers they must implement. Abstract classes capture the commonalities between classes, in the form of fields, implemented methods, and abstract methods that specify methods that all extending subclasses must implement. Common Fields - an Example Below is the familiar shape example. The first design uses an interface and three classes to define the shapes. The second design introduces the use of an abstract class to capture the common Posn field. Shapes with interface only +------------+ | IShape | |------------| +------------+ / \ | - - - - - - - - - - - - - - - - - - - - | | | +------------+ +------------+ +------------+ | Dot | | Square | | Circle | |------------| |------------| |------------| |Posn loc |-+ |Posn loc |--+--|Posn loc | | | | |int size | | |int radius | +------------+ | +------------+ | +------------+ | | | +------------+ | +-->| Posn |<-+ |------------| |int x | |int y | +------------+ Shapes with additional abstract class +------------+ | IShape | |------------| +------------+ / \ | +------------+ +------------+ +-->| Posn | | AShape | | |------------| |------------| | |int x | |Posn loc |--+ |int y | +------------+ +------------+ / \ --- | +------------------+------------------+ | | | +------------+ +------------+ +------------+ | Dot | | Square | | Circle | |------------| |------------| |------------| | | |int size | |int radius | +------------+ +------------+ +------------+ Common Methods If the subclasses of a union have identical implementations for a method, that method can be lifted into the abstract class. This has several benefits. One, it saves time and space by requiring only one implementation. Second, if you decide to change the implementation, you only have to do it in one place. For example, adding a distTo0() method to all shape classes only requires adding the method header to IShape and the concrete method to AShape. If a method differs across the subclasses, the method header is placed in the abstract class and labeled as abstract. The concrete methods then must appear in all subclasses just as was the case when the method heaader was declared in the common interface. For example, adding a perimiter() method to all shape classes requires a method header in IShape, an abstract method header in AShape, and a concrete method in each shape subclass. Below is the implementation of the design using an abstract class. Modify the class diagram above to included the new distTo0 and perimiter methods. Also, make some examples of using these two methods. A few things to notice: - The Posn field has been *lifted* to the abstract class AShape, because it is common to all of the shape classes. - Each shape class *extends* AShape. This means they *inherit* all of the fields and methods defined in AShape. The AShape classes is said to be a *superclass* and the others *subclasses*. - The abstract class has a constructor, even though it can not be instantiated directly. This constructor is used in the subclasses through the use of "super(Posn loc)". - The abstract class AShape implements IShape. This guarantees that any methods listed in IShape will need to be implemented by either AShape or its subclasses. - Any methods listed as abstract in AShape must be implemented by its subclasses, such as the perimeter() method. */ /* Represents an (x,y) location */ class Posn { int x; int y; Posn(int x, int y) { this.x = x; this.y = y; } // Returns the distance of this Posn to (0,0) double distTo0() { return Math.sqrt(x*x + y*y); } } /* Lists methods common to all shapes */ interface IShape { // Returns the distance of this shape's location to (0,0) double distTo0(); // Return the perimiter of this shape double perimiter(); } /* Defines fields and methods common to all shapes */ abstract class AShape implements IShape { Posn loc; AShape(Posn loc) { this.loc = loc; } // Returns the distance of this shape's location to (0,0) double distTo0() { return this.loc.distTo0(); } // Return the perimiter of this shape abstract double perimiter(); } /* A dot shape */ class Dot extends AShape { Dot(Posn loc) { super(loc); } // Return the perimiter of this shape double perimiter() { return 0; } } /* A square shape */ class Square extends AShape { int size; Square(Posn loc, int size) { super(loc); this.size = size; } // Return the perimiter of this shape double perimiter() { return 4 * this.size; } } /* A circle shape */ class Circle extends AShape { int radius; Circle(Posn loc, int radius) { super(loc); this.radius = radius; } // Return the perimiter of this shape double perimiter() { return Math.PI * 2 * this.radius; } } /* Activity - Adding More Fields and Methods Add the following to the shape classes. It is up to you to decide where each should appear (in the interface IShape, the abstract class AShape, the subclasses Dot, Square, and Circle, or some combination thereof). Remember! Use the design recipe in all cases, including modifying the class diagram above, using purpose statements, including templates, and making examples. 1. The method closerTo0, which determines whether this shape is closer to (0,0) than some other, given IShape. 2. The method area, that returns the area of this shape. 3. The method largerThan, that determines whether the area of this shape is larger than the area of some other, given IShape. 4. same methods, for determining whether this shape is the same as some other, given IShape. If you need to, refer back to lab 4 to review the design of same methods for unions. Activity - Adding a New Shape Now, add a new new class representing a rectangle shape. Notice how adding this class is made easier by the abstract class encapsulating the commonalities between all shapes. */