1 Object-Oriented Programming (Java), Unit 13 Kirk Scott

Preview:

Citation preview

1

Object-Oriented Programming (Java), Unit 13

Kirk Scott

2

Inheritance, Part II

• 13.1 Abstraction in Class Design• 13.2 Polymorphism and Dynamic

Binding• 13.3 Multiple Inheritance and Interfaces• 13.4 An Example from the Java API:

The Point Classes

• Hieronymus Bosch• The Garden of Earthly Delights

3

4

• Auguste Rodin• The Thinker

5

6

• M. C. Escher• Relativity

7

8

9

13.1 Abstraction in Class Design

10

13.1.1 The Level of Implementation of Object Characteristics in a Class Hierarchy, and Whether

Instances of Classes Should be Allowed

• Inheritance leads to two important questions.

• Where should instance variables and methods be implemented in an inheritance hierarchy?

• Are there classes which should never have instances of them constructed?

13.1.2 An Example of Needless Duplication—Implementation Too Low in the Hierarchy

• The assignment for Unit 12 involved a hierarchy of Food classes.

• The complete UML diagram for the requested classes is shown on the next overhead.

11

PackagedFood and BulkFood are both subclasses of Food

12

FoodV4

PackagedFoodV4 BulkFoodV4

13

• The written instructions for the classes in the Unit 12 assignment specified that both PackagedFoodV4 and BulkFoodV4 have a String variable named units.

• That means that if you expressly followed the instructions, both classes would contain code such as that shown on the following overhead.

• private String units;• …• public void setUnits(String unitsIn)

• {• units = unitsIn;• }• public String getUnits()• {• return units;• }

14

15

• Having this code in both classes is unnecessary repetition.

• Common elements such as the instance variable units and its get and set methods should be implemented in a superclass and inherited.

• The statements on the previous overhead give an indication of the answer to the question posed at the beginning:

• Where should instance variables and methods be implemented in an inheritance hierarchy?

• Attributes and operations should be implemented at the highest level possible in an inheritance hierarchy.

16

17

13.1.3 A Logical Explanation of Whether Instances should be Allowed

• Take a look at this inheritance hierarchy again:– Kingdom: Animalia

• Phylum: Chordata– Class: Mammalia

» Order: Primates» Family: Hominidae» Genus: Homo» Species: sapiens

18

• In the biological world, every kind of animal can ultimately be described as a single species.

• There can be instances of Homo sapiens.• There can be no instances of the

superclasses. • There can be no instance of Animalia, for

example, because there is no such thing as a generic animal.

• Consider the hierarchy of classes in the exercises from the previous unit again.

• Does it make sense to create instances of the Food class, or only instances of the classes PackagedFood and BulkFood?

• If there is no such thing as a food which is not a packaged food or a bulk food, then there should be no instances of the Food class.

• There should only be instances of the PackagedFood or the BulkFood classes.

19

• The statements on the previous overhead give an indication of the answer to the second question posed at the beginning:

• Are there classes which should never have instances of them constructed?

• The answer is yes, some classes should never have instances of them constructed.

20

• The questions of where to implement features and whether classes should have instances are related.

• Some classes exist for the purposes of categorizing elements of a hierarchy.

• They categorize by means of the fact that they gather together certain characteristics which all of their subclasses should have.

• However, those classes which simply categorize would not have instances themselves.

21

22

13.1.4 Trying to Provide a Method in Java for Classes Which Would Have Different Implementations of it

• Suppose you wish all classes in the food hierarchy to implement the getUnitCost() method.

• In theory, it would be desirable to implement a method common to all of the classes in the hierarchy in the Food class, at the top of the hierarchy.

• Because the unit cost is computed differently for the two subclasses, the method would have to be overridden in each.

• It is desirable to be able to specify that a given method exist for all classes in an inheritance hierarchy while having a separate implementation in each.

• Two undesirable ways of accomplishing this are given on the following overhead.

23

• 1. You could implement one of the subclass versions in the superclass.

• Then the method would only have to be overridden in the other subclass.

• 2. You could declare a method in the superclass with an empty body, containing no code.

• Then you would have override the method with real (and differing) implementations in both of the subclasses.

24

• In either case the method as implemented in the superclass could not be correctly called on objects of the superclass.

• This is why these two solutions are undesirable.• In the first case it would be a method

implementation that applied to just one of the subclasses, not a common implementation for all.

• In the second case it would be a dummy implementation of no use at all.

25

26

13.1.5 The Best Solution: An Abstract Method in the Superclass—Forcing the Class Itself to be Abstract

• The correct solution is to declare the method in the superclass to be abstract.

• An abstract method has no braces or body and contains no code.

• It does specify a return type and a parameter list.

• It would appear in the Food class as follows:

• public abstract double getUnitCost();

27

• Declaring a method abstract has three critical effects:

• If a class contains an abstract method, the class itself has to be declared abstract

• It is not possible to construct instances of an abstract class.

• It requires that the method be overridden in each immediate, concrete subclass.

• In this example, the Food class would have to be declared in the following way:

• public abstract class Food

28

29

13.1.6 Abstract Classes can still have Constructors

• An abstract class groups together sets of attributes and operations which are to be shared by its subclasses.

• It is not possible to construct instances of an abstract class in a user program.

• However, an abstract class may contain constructors

• Remember that constructors in the concrete subclasses of an abstract class may depend on the existence of constructors in the superclass.

30

13.1.7 Example Code

• The code for the food classes, rewritten using abstraction, will be given shortly.

• They will be version 5 of the classes, V5.• Unit 12 ended with V3 and the unit 12 assignment asked

you to write V4.• FoodV5 will be an abstract class.• The getUnitCost() method is declared abstract in

FoodV5.• The implementations of the method in the packaged food

and bulk food subclasses will differ.

• The getUnitCost() method for a packaged food, PackagedFoodV5, calculates the unitCost by dividing the itemCost by the size.

• The getUnitCost() method for a bulk food, BulkFoodV5, is a simple get method which returns the value of the unitCost instance variable.

31

• In the previous unit, in the Food/TaxedFood hierarchy, the setMarkupToThisMarkup() method was given

• The FoodV4 class included a setBrandToThisBrand() method—which you should have provided as part of the unit 12 assignment

• The Food/BulkFood/PackagedFood hierarchy under consideration in this unit will continue to use the setBrandToThisBrand() method

32

• When looking at the example code, keep these points in mind:

• An abstract class will most likely have instance variables and get and set methods, which will be inherited, as usual.

• It may also have methods like setBrandToThisBrand(), which will also be inherited, as usual.

33

34

• public abstract class FoodV5• {• private String brand;• private String productName;• private String units;• public FoodV5(String brandIn, String

productNameIn, String unitsIn)• {• brand = brandIn;• productName = productNameIn;• units = unitsIn;• }• public void setBrand(String brandIn)• {• brand = brandIn;• }• public String getBrand()• {• return brand;• }

35

• public void setProductName(String productNameIn)

• {• productName = productNameIn;• }• public String getProductName()• {• return productName;• }• public void setUnits(String unitsIn)• {• units = unitsIn;• }•

public String getUnits()• {• return units;• }

36

• public void setBrandToThisBrand(FoodV5 anotherFood)

• {• String tempBrand = anotherFood.getBrand();

• setBrand(tempBrand);• }• public abstract double getUnitCost();• }

37

• public class PackagedFoodV5 extends FoodV5• {• private double size;• private double itemCost;• public PackagedFoodV5(String brandIn, String

productNameIn, String unitsIn,• double sizeIn, double itemCostIn)• {• super(brandIn, productNameIn, unitsIn);• size = sizeIn;• itemCost = itemCostIn;• }• public void setSize(double sizeIn)• {• size = sizeIn;• }• public double getSize()• {• return size;• }

38

• public void setItemCost(double itemCostIn)• {• itemCost = itemCostIn;• }• public double getItemCost()• {• return itemCost;• }• public double getUnitCost()• {• return itemCost / size;• }• }

39

• public class BulkFoodV5 extends FoodV5• {• private double unitCost;• public BulkFoodV5(String brandIn, String productNameIn,

String unitsIn, double unitCostIn)• {• super(brandIn, productNameIn, unitsIn);• unitCost = unitCostIn;• }• public void setUnitCost(double unitCostIn)• {• unitCost = unitCostIn;• }• public double getUnitCost()• {• return unitCost;• }• public double findCost(double amount)• {• return amount * unitCost;• }• }

40

13.2 Polymorphism and Dynamic Binding

• This section basically repeats information given in Unit 12.

• This section specifically uses the terminology polymorphism and dynamic binding in the explanations.

• It also gives concrete examples using the class hierarchy developed in homework to show how polymorphism and dynamic binding apply in the specific case of parameter passing.

41

42

13.2.1 Superclass References to Subclass Objects are OK. This is Polymorphism

• As pointed out in Unit 12, in Java it is syntactically possible to have a superclass reference to a subclass object.

• Given any particular reference, it could refer to an object of its own class or any of its subclasses.

• The type of the reference doesn’t tell the specific type of the object referred to.

• The term polymorphism is used to summarize the idea that a reference may refer to different kinds of objects.

• This term comes from Greek roots meaning many and form.

43

44

13.2.2 Superclass References to Subclass Objects only have Access to Methods defined in the Superclass

• Also, as pointed out in Unit 12, superclass references to subclass objects are distinctly limited.

• A superclass reference cannot “know” about any instance variables or methods which are defined below it in the hierarchy.

• If a method is not defined for the superclass, but is only defined in the subclass, it is not possible to call this method on a superclass reference to a subclass object.

45

13.2.3 If an Overridden Method is called on a Superclass Reference to a Subclass Object, the Version in the Subclass

will be used. This is Dynamic Binding

• Suppose each subclass in an inheritance hierarchy overrides a given superclass method.

• Suppose also that the method is called on a superclass reference to a subclass object.

• Calling the method on the superclass reference doesn't cause a problem because the method is defined in the superclass.

• When the call is made the version of the method defined in the subclass will be used.

46

• The term dynamic binding means that the decision of which version of a method to use will be based on the actual type of the object referred to at run time, not the formal type of the reference as declared in the code.

• It was pointed out previously that if the method were not overridden in the subclass, the call would still be OK.

• The version of the method the subclass inherited from the superclass would be used.

• The key point is that if it is overridden, the overridden version will be used.

• The overall conclusion is this: • If a method is called on a superclass

reference to a subclass object, as long as the method is defined for the superclass, the call is OK.

• Dynamic binding means that whatever version of the method is valid for that subclass, whether inherited or overridden, will be used.

47

48

13.2.4 Code Examples (Based on Previous Example, but Shortened with Ellipses)

• This section repeats the code for the FoodV5, PackagedFoodV5, BulkFoodV5 class hierarchy, but with ellipses.

• This code will then be used in reviewing concretely how polymorphism and dynamic binding work.

• public abstract class FoodV5• {• private String brand;• private String productName;• private String units;• …• public void setBrand(String brandIn)• {• brand = brandIn;• }• public String getBrand()• {• return brand;• }• …• public void setBrandToThisBrand(FoodV5

anotherFood)• {• String tempBrand = anotherFood.getBrand();• setBrand(tempBrand);• }• …• public abstract double getUnitCost();• } 49

50

• public class PackagedFoodV5 extends FoodV5• {• private double size;• private double itemCost;• …• public void setSize(double sizeIn)• {• size = sizeIn;• }• public double getSize()• {• return size;• }• …• public double getUnitCost()• {• return itemCost / size;• }• }

51

• public class BulkFoodV5 extends FoodV5• {• private double unitCost;• …• public void setUnitCost(double unitCostIn)• {• unitCost = unitCostIn;• }• public double getUnitCost()• {• return unitCost;• }• …• }

52

13.2.5 Constructing Objects and Assigning References

• Suppose you have a FoodV5 superclass reference to a PackagedFoodV5 object, such as shown here:

• FoodV5 foodReference;• PackagedFoodV5 packagedFoodReference = new PackagedFoodV5(…);

• foodReference = packagedFoodReference;

53

13.2.6 An Invalid Call: Calling a Method Defined Only in the Subclass on a Superclass Reference

• The following calls are not possible because the methods are not defined for the superclass:

• /* NO! NO! NO! */• foodReference.setSize(…);• …foodReference.getSize();• The same would be true if FoodV5 were a

superclass reference to a BulkFoodV5 object and the calls were to the methods setUnitCost() and getUnitCost().

54

13.2.7 The Method can be called if the Subclass Reference is Recovered

• If the subclass reference is recovered, there is no problem calling a subclass method, as illustrated here:

• PackagedFoodV5 recovered = (PackagedFoodV5) foodReference;

• recovered.setSize(…);

55

13.2.8 Calling setBrandToThisBrand() on a Superclass Reference

• Suppose you call the setBrandToThisBrand() method on a superclass reference to a subclass object:

• FoodV5 foodReference;• PackagedFoodV5 packagedFoodReference = new PackagedFoodV5(…);

• foodReference = packagedFoodReference;• foodReference.setBrandToThisBrand(…);

• The call on a superclass reference is allowed because this method is defined for the superclass.

• The method is not overridden in the subclass, so the version inherited from the superclass is used.

56

57

13.2.9 Automatic Conversion to a Superclass Reference Occurs when a Subclass Object is Passed

as the Actual Parameter

• Here is a call to the setBrandToThisBrand() method with a subclass reference as the explicit parameter:

• PackagedFoodV5 packagedFoodReference = new PackagedFoodV5(…);

• …setBrandToThisBrand(packagedFoodReference);

• A subclass reference can be passed when the formal parameter is a superclass reference.

• Automatic conversion to a superclass reference occurs.

58

• Here is the code for the method again. • The formal parameter, anotherFood,

becomes a superclass reference to the explicit parameter, packagedFoodReference.

•• public void setBrandToThisBrand(FoodV5 anotherFood)• {• String tempBrand = anotherFood.getBrand();• setBrand(tempBrand);• }

59

13.2.10 Calling a Superclass Method on the Formal Parameter in the Body of the Method

• Within the body of the method the explicit parameter is used in this one line of code:

• String tempBrand = anotherFood.getBrand();

• This call is OK because the getBrand() method is defined in the superclass.

• The getBrand() method is not overridden in the subclass, and the call on the superclass reference to the subclass object makes use of the version of the method inherited from the superclass.

60

13.2.11 Calling an Overridden Method on the Formal Parameter in the Body of the Method

• The next example is kind of artificial.• It is unlikely that you would often write

code in this way, but it does provide an immediate example of the syntactical question of interest.

• Consider a method that only exists in the BulkFood class.

• Let the method be setUnitCostToThisUnitCost().

• This could only exist in BulkFood because only BulkFood has a unitCost instance variable that can be set.

• The unitCost of PackagedFood is calculated.

• PackagedFood doesn’t have a unitCost instance variable that can be set.

61

• The setUnitCostToThisUnitCost() method obtains a unitCost from the explicit parameter and assigns it to the implicit parameter.

• The formal parameter is declared to be a superclass reference, FoodV5, to allow for actual parameters of either subclass.

62

• Having a subclass method with a formal parameter of a superclass type is part of what makes this example unrepresentative.

• However, syntactically, it’s OK.• A subclass “knows” about superclasses,

so a subclass can make use of a superclass.

63

• Not only is it syntactically OK for the explicit parameter to be a superclass type.

• The point is that the explicit parameter of the method could be either a PackagedFoodV5 or a BulkFoodV5 object.

• In the body of the method, getUnitCost() is called on the explicit parameter.

• A unitCost can be obtained from either of the subclasses.

64

65

• This is what the method code looks like:• public void setUnitCostToThisUnitCost(FoodV5 anotherFood)• {• double tempUnitCost = anotherFood.getUnitCost();• setUnitCost(tempUnitCost);• }

• Keep in mind that the point of the example, artificial though it may be, is to consider another case where dynamic binding applies.

66

13.2.12 Dynamic Binding Means that the Appropriate Version of the Method is Called on the Formal Parameter, which is a Superclass Reference

• The key element of the example is the following line of code in the body of the setUnitCostToThisUnitCost() method:

• double tempUnitCost = anotherFood.getUnitCost();

• When a call is made to the setUnitCostToThisUnitCost() method, a subclass object will be accepted as the explicit parameter.

• The parameter is automatically converted to a superclass reference.

67

• The getUnitCost() method is declared abstract in the FoodV5 class, and different implementations exist in each of the subclasses.

• Because the getUnitCost() method exists in the superclass, it can be called on the superclass reference to a subclass object passed in as a parameter.

• If the formal parameter, the superclass reference anotherFood, refers to a PackagedFoodV5 object, then the getUnitCost() method found in the PackagedFoodV5 class will be used.

• If the formal parameter, the superclass reference anotherFood, refers to a BulkFoodV5 object, then the getUnitCost() method found in the BulkFoodV5 class will be used.

68

• The phrase dynamic binding means that the system determines the type of the actual parameter referred to by the formal parameter at run time and uses the corresponding version of getUnitCost().

69

70

13.2.13 Recapitulation of Polymorphism and Dynamic Binding

• Polymorphism means that superclass references to subclass objects are possible.

• Methods that are defined for the superclass can be called on a superclass reference.

• A superclass reference does not have access to methods that are only defined in the subclass.

• Dynamic binding means that at run time the system determines the actual object type of a superclass reference.

• If a method is called on a superclass reference, if the method has been overridden in the subclass, the system will use the version of the method existing in the subclass, not the version in the superclass.

• If the method has not been overridden, the inherited version defined in the superclass will be used in any case.

71

• It is possible to pass subclass objects as parameters to methods where the formal, explicit parameter is of the superclass type.

• When this is done, automatic conversion occurs, and the formal parameter becomes a superclass reference.

• The rules for dynamic binding apply to these (polymorphic) superclass references.

72

73

13.3 Multiple Inheritance and Interfaces

74

13.3.1 What is Multiple Inheritance?

• The UML diagram on the following overhead illustrates multiple inheritance.

• The idea is that the Cow class has two parent classes instead of one.

75

Animal Food

Cockroach Cow Celery

76

13.3.2 Java doesn't Support Multiple Inheritance. It has Interfaces instead

• Java does not support multiple inheritance.

• A class can only have one immediate parent.

• Syntactically, it is only possible for a class to extend one other class.

77

• Instead of multiple inheritance, Java has interfaces.

• An interface contains no instance variables.

• An interface is a specification of a set of methods.

• An interface contains no implementations for the specified methods.

• The methods in the interface definition are not given an access modifier.

• They are public by default.• Declaring them public is not a fatal error.

78

79

• A class can implement an interface.• Implementing the interface means

implementing all of the methods listed in the interface specification.

• The implementations of the methods have to be declared public.

• Implementing the interface also means supplying all of the instance variables that might be needed to support these methods.

• This is necessary because the interface specification includes no instance variables.

80

• In a certain sense an interface is kind of like a completely abstract class.

• Some authors eschew the foregoing explanation, but from an empirical point of view, it can be useful.

• The most immediate difference between an abstract class and an interface is the interface’s lack of instance variables.

81

82

13.3.3 What is an Interface?

• An interface will be introduced into the example class hierarchy.

• The interface will specify the characteristic of taxability.

• The following UML diagram illustrates such an interface.

83

FoodV5

PackagedFoodV5 BulkFoodV5

TaxedPackagedFoodV5 TaxedBulkFoodV5

«interface»Taxable Interface

84

• The hierarchy should still support both packaged and bulk foods.

• The hierarchy should also support both taxed and untaxed food items of both kinds.

• Taxation should be handled in the same way for both packaged and bulk foods.

• Implementing the interface requires that both the untaxed PackagedFood and BulkFood classes be extended into new, taxed subclasses.

85

13.2.4.1 Defining an Interface

• Let the Taxable interface be defined as shown below.

• public interface Taxable• {• void setTaxRate(double TaxRateIn);• double getTaxRate();• double findTaxValuePerUnit();• }

• Notice that there are syntactical differences and similarities between the declarations of abstract methods and methods in interfaces.

• This was the example abstract method given earlier:

• public abstract double getUnitCost();

86

• On the one hand, you don’t declare interface methods public and abstract

• On the other hand, you do give the return type, name, and parameter list

• And these items are simply followed by a semicolon and no braces, no code, no method definition, just like with an abstract method

87

88

• Although the variable is not shown, any class that implements the Taxable interface will have to have a double instance variable named taxRate.

• The implementing class will have to have these two methods: setTaxRate() and getTaxRate() and the variable is needed in order to support them.

• The class will also have to have a method findTaxValuePerUnit().

• Because unitCost is an instance variable in BulkFoodV5 but calculated in PackagedFoodV5, the implementation of findTaxValuePerUnit() will differ in the two taxed food classes that implement it.

89

90

13.2.4.2 Syntactical Details of Interfaces

• An interface is stored in a file with the same name as the interface.

• An interface definition is stored in a .java file (like a class).

• The interface is declared public.• However, an interface is not a class.• There can be no instances of it.

• An interface is not a class, so it can’t have subclasses

• Because an interface doesn’t contain any implementations, an interface cannot implement another interface

• It is true that an interface can have sub-interfaces

• One interface can extend another

91

• Sub-interfaces are beyond the scope of this course

• For our purposes, interfaces will be used for categorization, like abstract superclasses

• They will exist in isolation as mechanisms for grouping together a set of characteristics shared by implementing classes

• We will not develop them into a hierarchy with inheritance characteristics.

92

13.3.5 An Example of a Class Implementing an Interface

• The keyword for a class that makes use of an interface is “implements”

• A class implements an interface• This means that it implements all of the

methods specified in the interface• It also provides all needed instance

variables• An example follows

93

94

• public class TaxedPackagedFoodV5 extends PackagedFoodV5 implements Taxable

• {• private double taxRate;• public TaxedPackagedFoodV5(String brandIn, String• productNameIn, String unitsIn,• double sizeIn, double itemCostIn, double• taxRateIn)• {• super(brandIn, productNameIn, unitsIn,

sizeIn,• itemCostIn);• taxRate = taxRateIn;• }

95

• public void setTaxRate(double taxRateIn)• {• taxRate = taxRateIn;• }• public double getTaxRate()• {• return taxRate;• }• public double findTaxValuePerUnit()• {• return (getItemCost() / getSize()) *

taxRate;• }• }

96

• The TaxedPackagedFoodV5 class first extends its parent class and then implements the interface.

• The needed instance variable, taxRate, is declared as part of the class definition, and it is used in the constructor.

• Get and set methods are provided for the instance variable.

• An appropriate findTaxValuePerUnit() method is implemented for this class.

97

13.3.6 Summary of the Interface Idea

• You inherit nothing from an interface, neither instance variables nor methods.

• If you choose to implement an interface, what you get is a set of requirements that have to be met.

• Certain methods have to be implemented, and anything else needed in the class in order to support these methods, such as instance variables, also has to be supplied.

• Interfaces are as close as Java comes to supporting the concept of multiple inheritance.

• In future courses you will discover that interfaces are a very powerful construct.

• They are very useful in designing object-oriented programs more advanced than the examples given in this course.

98

99

13.4 An Example from the Java API: The Point Classes

100

13.4.1 Example Excerpts from the Java API Documentation for the Point Classes

• The rest of this section consists of snippets taken from the Java API documentation.

• As you read the snippets, you will find that the documentation for these classes specify inheritance, abstraction, and interfaces within and among them.

• The following section is a running commentary on those aspects of the documentation.

• java.lang Class Object

• java.lang.Object• public class Object• Class Object is the root of the class

hierarchy. • Every class has Object as a superclass.• All objects, including arrays, implement the

methods of this class. 101

102

• java.awt.geom Class Point2D

• java.lang.Object• java.awt.geom.Point2D• All Implemented Interfaces: • Cloneable • Direct Known Subclasses: • Point, Point2D.Double, Point2D.Float • public abstract class Point2D extends Object• implements Cloneable• The Point2D class defines a point representing a

location in (x, y) coordinate space. • This class is only the abstract superclass for all objects

that store a 2D coordinate. The actual storage representation of the coordinates is left to the subclass.

103

• Nested Class Summary• static class Point2D.Double• The Double class defines a point specified

in double precision.• static class Point2D.Float• The Float class defines a point specified in

float precision.• Constructor Summary• protected Point2D()• This is an abstract class that cannot be

instantiated directly.

104

• java.awt.geom Class Point2D.Double

• java.lang.Object java.awt.geom.Point2D• java.awt.geom.Point2D.Double• All Implemented Interfaces: • Cloneable • Enclosing class: • Point2D • public static class Point2D.Double• extends Point2D• The Double class defines a point specified in

double precision.

105

• Nested Class Summary  • Nested classes/interfaces inherited from class

java.awt.geom.Point2D• Point2D.Double, Point2D.Float  • Field Summary• double x• The X coordinate of this Point2D.• double y• The Y coordinate of this Point2D.  • Constructor Summary• Point2D.Double()• Constructs and initializes a Point2D with coordinates

(0, 0).• Point2D.Double(double x, double y)• Constructs and initializes a Point2D with the specified

coordinates.

106

• Method Summary• double getX()• Returns the X coordinate of this Point2D in double

precision.• double getY()• Returns the Y coordinate of this Point2D in double

precision.• void setLocation(double x, double y)• Sets the location of this Point2D to the specified double

coordinates.• String toString()• Returns a String that represents the value of this

Point2D.  • Methods inherited from class java.awt.geom.Point2D• clone, distance, distance, distance, distanceSq,

distanceSq, distanceSq, equals, hashCode, setLocation  • Methods inherited from class java.lang.Object• finalize, getClass, notify, notifyAll, wait, wait, wait

107

13.4.2 How the Point Classes Exhibit Inheritance, Abstraction, and Interfaces

• Reading the API documentation it is possible to see the following:

• Object is the parent class of Point2D, which is the parent class of Point, Point2D.Double, and Point2D.Float.

• Point2D is an abstract class and there can be no instances of it.

• The subclasses implement various interfaces.

108

13.4.3 The Treatment of Instance Variables in the Point Classes

• The Point2D (super) class does not have any instance variables.

• The declaration of the instance variables for the coordinates of a point, x and y, are in the subclasses.

• The x and y coordinates of the Point class are typed integer.

• The x and y coordinates of the Point2D.Double and Point2D.Float classes are typed double and float, respectively.

109

• It is not possible to declare instance variables abstract.

• Only methods can be declared abstract.• Therefore it is not syntactically possible to

declare "abstract" instance variables x and y in the superclass, Point2D.

• As noted earlier, it is not possible to "override" instance variables.

• Although syntactically possible, it would be incorrect to declare instance variables x and y of a given type in Point2D and then declare instance variables with the same names in the subclasses.

• In effect, what you see in this part of the point classes is a means of getting around this limitation and having a set of sibling classes with variables of the same name but of different types.

110

• In order to support three different kinds of points which differ only in the types of their instance variables, it is necessary to put the declarations of the instance variables in each of the subclasses.

• Because the meaning of the x and y coordinates is not changed by their numeric types, it is logically acceptable to have instance variables with the same names in the subclasses.

111

112

13.4.4 An Inherited Method Among the Point Classes

• Methods which use the coordinate instance variables are defined in the superclass, Point2D, and inherited by the subclasses.

• For example:• abstract  double getX()• Returns the X coordinate of this Point2D in

double precision.

• The abstract superclass, Point2D, has this similarity with an interface:

• It defines methods which use the expected instance variables, but it does not declare those variables for the subclasses to inherit.

113

• The getX() method, typed to return a double value, can work because any other numeric type can be held in a double.

• In other words, this trickery works for the same reason you are allowed to assign the contents of an integer variable to a double variable without casting.

114

115

13.4.5 Nested or Inner Classes, as Illustrated by the Point Classes

• The classes Point2D.Double and Point2D.Float are listed as nested classes of Point2D.

• They may also be referred to as inner classes.

• This means that the definitions of both Point2D.Double and Point2D.Float are completely contained within the braces of the code for the Point2D class.

• Inner classes always have to be referred to by their compound names using dot notation such as Point2D.Double.

• When importing inner classes, it is sufficient to specify the name of the outer class in the import statement.

• The inner class is imported as a consequence.

116

117

• Being a subclass and being an inner class are independent of each other.

• The subclass Point is not an inner class of Point2D while the other two subclasses are.

• The differing implementations of the three subclasses came about for historical reasons.

• The fact that the code for an inner class is completely contained within the code for the outer class in general has significant implications.

• It has no particular importance for us for the point classes.

118

• This is just an initial introduction to the fact that things known as inner classes exist.

• In a future unit you will see that inner classes are very useful when creating event driven programs.

• Their usefulness derives from the fact that the code for a class completely contained in another class has direct access to the instance variables of the containing class.

119

120

The End