Presentation is loading. Please wait.

Presentation is loading. Please wait.

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

Similar presentations


Presentation on theme: "1 Object-Oriented Programming (Java), Unit 12 Kirk Scott."— Presentation transcript:

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

2 2 Inheritance, Part I 12.1 What is Inheritance? 12.2 Writing the Code for Subclasses 12.3 Access to Instance Variables and Overriding Methods 12.4 A Note on the Meaning of Inheritance 12.5 The Key Word super, Methods, and Construction 12.6 References to Classes and Subclasses in Programs and Methods

3 3 12.1 What is Inheritance?

4 4 12.1.1 Superclass/Subclass, Parent Class/Child Class Terminology The class at the top of an inheritance hierarchy has nothing above it. Any other class has exactly one class immediately above it in the hierarchy. Any given class may have more than one class above it, at different levels in the hierarchy. The class immediately above a given class may be called the parent class or superclass. All classes above it are known generally as superclasses. A class can have more than one class immediately below it. Below that may be others, and so on. A class immediately below a given class may be called a child class or a subclass. All classes below it are known generally as subclasses.

5 5 12.1.2 "Is-a" or "Is-a-Kind-of" Relationships The relationship between items in such a hierarchy can be described as an “is a” or “is a kind of” relationship. Any class that appears lower down in the hierarchy must be an example of, or a more specific kind of, whatever classes appear above it in the hierarchy. In the field of biology the classification of all living things is based on this idea. This is referred to as taxonomy. The taxonomy of human beings is shown below. This illustrates one relatively complete branch of an inheritance hierarchy.

6 6 Kingdom: Animalia –Phylum: Chordata Class: Mammalia –Order: Primates »Family: Hominidae » Genus: Homo » Species: sapiens

7 7 12.1.3 Inheritance Hierarchies are Tree- Like The UML-like diagram below illustrates the tree-like nature of inheritance hierarchies. This is described as a tree, although it is customary to represent it “upside down”, with the root at the top.

8 8

9 9 12.1.4 In Java the Root Class and the Default Parent Class is Named Object In Java the single class at the top of the hierarchy, or the root of the tree, is a class named Object. All system supplied classes are arranged in a hierarchy beneath this class. When a programmer writes a class and a parent class is not specified, such classes become children, or immediate subclasses, of the Object class. There is a syntax allowing programmers to specifically make one class a subclass of another. It will be covered later

10 10 12.1.5 Subclasses Inherit Instance Variables and Methods, but Not Constructors Classes in the hierarchy are related by inheritance. Any class that has classes above it in the hierarchy inherits characteristics of those superclasses. These characteristics include variables and methods. Constructors are not inherited. It is natural, and possible, for subclasses to add attributes which do not exist in the superclasses. This is the main way in which subclasses distinguish themselves from their superclasses. There may also be situations where it is undesirable to inherit characteristics. There is syntax which thwarts inheritance. It will be covered later.

11 11 12.1.6 Do Not Confuse Individual Inheritance with Class Inheritance Different uses of the term inheritance can potentially lead to confusion. Inheritance can be used to refer to the characteristics an individual child receives from a particular parent, for example. This is not the sense of inheritance as it's used here. The taxonomic example shows inheritance among categories, not individuals. This does illustrate the sense of inheritance as it's used here. For example, the genus Homo is the parent class of the species sapiens in the hierarchy. Homo doesn't represent some individual parent and sapiens doesn't represent some individual child.

12 12 12.1.7 The Hierarchy Containing Rectangle2D in the Java API Documentation The Java API documentation for the class Rectangle2D shows an inheritance hierarchy. java.lang.Object java.awt.geom.RectangularShape java.awt.geom.Rectangle2D Object is the parent class of RectangularShape and RectangularShape is the parent class of Rectangle2D. The class names are fully qualified using dot notation to show which packages they are in, java.lang or java.awt.geom. Package membership does not indicate inheritance relationships.

13 13 12.2 Writing the Code for Subclasses

14 14 12.2.1 The Food Class Example Consider a class, FoodV1, which represents kinds of food items from the point of view of the store where they are sold. The instance variables for this class are name, wholesaleCost, and markup. This class does not use the keyword extends. This means that by default it is a subclass of the Object class.

15 15 public class FoodV1 { private String name; private double wholesaleCost; private double markup; public FoodV1() { } public void setName(String nameIn) { name = nameIn; } public String getName() { return name; }

16 16 public void setWholesaleCost(double wholesaleCostIn) { wholesaleCost = wholesaleCostIn; } public double getWholesaleCost() { return wholesaleCost; } public void setMarkup(double markupIn) { markup = markupIn; } public double getMarkup() { return markup; } public double getPrice() { return (wholesaleCost + wholesaleCost * markup); }

17 17 12.2.2 Creating Subclasses It is possible to create a class, TaxedFoodV1, which is a subclass of the FoodV1 class. Here is a UML diagram showing the inheritance relationship between these classes and the Object class:

18 18

19 19 12.2.3 The Keyword extends The keyword for specifying a subclass is extends. Syntactically, the child specifies its one parent; the parent doesn’t specify its potentially many children. Here is the code for the TaxedFoodV1, a child class of FoodV1:

20 20 public class TaxedFoodV1 extends FoodV1 { private double taxRate; public TaxedFoodV1() { } public void setTaxRate(double taxRateIn) { taxRate = taxRateIn; } public double getTaxRate() { return taxRate; }

21 21 12.2.4 The Inheritance of Instance Variables The TaxedFoodV1 class has one instance variable of its own, taxRate. The class also inherits all of the instance variables of the class FoodV1. An object of this class has all of the following instance variables: nameinherited wholesaleCostinherited markupinherited taxRatenot inherited

22 22 12.2.5 The Inheritance of Methods The TaxedFoodV1 class has get and set methods for the instance variable taxRate defined in it. It also inherits all of the methods of the class FoodV1. Assuming that the mytaxedfood object has been constructed, these calls to the inherited methods can be freely made: mytaxedFood.setname(“Peas”); double retrievedcost = mytaxedFood.getWholesaleCost(); double retrievedprice = mytaxedFood.getPrice();

23 23 12.2.6 Constructors The TaxedFoodV1 class has a default constructor. An instance of the class can be constructed as usual: TaxedFoodV1 mytaxedFood = new TaxedFoodV1();

24 24 12.3 Access to Instance Variables and Overriding Methods

25 25 12.3.1 Inherited Instance Variables Are Not Directly Accessible Both instance variables and methods are inherited. Inherited instance variables declared private in the superclass (as they should be) are not directly accessible in the subclass. When using an instance of a subclass, it is possible to work with the object’s inherited instance variables by using the inherited get and set methods.

26 26 12.3.2 Thwarting Inheritance by Overriding Methods As subclasses become more specific, it is possible that an inherited method does not completely accomplish what needs to be accomplished. It is syntactically possible for a subclass to have a method with the same name as a method in one of its superclasses, and with the same parameter list. This is referred to as overriding the inherited method. If a call is made on an object of the subclass using that method name, the version of the method defined in the subclass is used, not the version in the superclass. Inheritance is thwarted by overriding.

27 27 12.3.3 Do Not Confuse Overriding with Overloading It is also possible to write a method in a subclass with the same name as a method in one of its superclasses, but with a different parameter list. In this case you have not overridden the inherited method. This is overloading. The two should not be confused.

28 28 12.3.4 An Example Illustrating Overriding The method getPrice() as defined in the class FoodV1 calculates a checkout price based on the wholesale cost of the item and the markup charged by the store. The checkout price for a taxed food item should include the tax on that item. This shows how the method might be correctly implemented in the TaxedFoodV1 class:

29 29 public double getPrice() { double retrievedCost; double retrievedMarkup; double costPlusMarkup; double price; retrievedCost = getWholesaleCost(); retrievedMarkup = getMarkup(); costPlusMarkup = retrievedCost + retrievedCost * retrievedMarkup; price = costPlusMarkup + costPlusMarkup * taxRate; return price; }

30 30 12.3.5 Lack of Direct Access There is no direct access to the inherited instance variables. The code above has to use the get methods to access the inherited variables: retrievedCost = getWholesaleCost(); retrievedMarkup = getMarkup();

31 31 12.3.6 Remembering the Implicit Parameter The same calls could be written with the implicit parameter. The retrieved values come from whatever object the getPrice() method was called on. retrievedCost = this.getWholesaleCost(); retrievedMarkup = this.getMarkup();

32 32 12.3.7 Review of Lack of Direct Access and Overriding The implicit parameter of the call to getPrice(), a TaxedFoodV1 object, would have wholesaleCost and markup variables by inheritance. Inherited variables can only be accessed through inherited get methods. Sometimes it is desirable to write an implementation of a specific method in a subclass which differs from the implementation that it would otherwise inherit. This is overriding.

33 33 12.3.8 Using the Overridden Method Suppose that the following objects were constructed: FoodV1 myfood = new FoodV1(); TaxedFoodV1 yourfood = new TaxedFoodV1(); Suppose also that set methods had been called so that their price, markup, and taxRate variables had been set.

34 34 Now consider the following two calls: double x = myfood.getPrice(); double y = yourfood.getPrice(); The two calls to getPrice() in the lines of code above are to two different versions of the method. Which version of the method is called depends on which kind of object it is called on, an instance of FoodV1 or an instance of TaxedFoodV1.

35 35 12.3.9 Inheritance from Multiple Levels Consider the following general inheritance hierarchy:

36 36 If methodX() is implemented in the Top class and not implemented in the other two classes, then it is inherited by both Middle and Bottom. If methodX() is implemented in Middle, then it does not exist for objects of the Top class. It is inherited by the Bottom class. If methodX() is implemented in the Top class, overridden in the Middle class, and inherited by the Bottom class, the version nearest to the Bottom class as you move upwards through the hierarchy is inherited. This is the version implemented in the Middle class.

37 37 12.3.10 Instance Variables Can't Be Overridden It is not possible to override instance variables. It is syntactically possible to declare instance variables in subclasses with the same name as instance variables in its superclasses. It is a mistake to do something like this. It will be extremely difficult to unravel the meaning of the code. It is also a problem conceptually. Instance variables should represent inherent characteristics of classes. If it seems desirable to change an instance variable in a subclass, that’s a sign that that class is in the wrong place in the inheritance hierarchy.

38 38 12.4 The Meaning of Inheritance: Some Differences with the Sun Java Tutorial Presentation If you haven’t looked at the Java Tutorial, then there is no need to consider this section.

39 39 12.5 The Key Word super, Methods, and Construction

40 40 12.5.1 Using super to Call an Overridden Method In overriding the getPrice() method, the majority of the code simply duplicated the logic of the method being overridden. It was necessary to get the price including the markup and then apply the tax rate to that. Finding the price with the markup is exactly what the getPrice() method does in the superclass. The example below shows how it is possible to make use of the method as defined above it in the hierarchy in order to implement the overriding method lower down in the hierarchy:

41 41 public double getPrice() { double price; price = super.getPrice(); price = price + price * taxRate; return price; } At execution time the key word super signals that the call to getPrice() is not a recursive call. The system looks in the hierarchy for the nearest class above the current class where getPrice() is implemented, and uses the version found there.

42 42 12.5.2 Subclass Constructors Don't Have Access to Inherited Instance Variables The keyword super also arises when writing subclass constructors which take parameters. Constructors in a subclass also do not have direct access to the (private) instance variables inherited from the superclass. super is needed in order to write a constructor for the TaxedFoodV1 class which would take parameters for the inherited instance variables wholesaleCost and markup.

43 43 12.5.3 If the Programmer Writes a Constructor, the System Doesn't Supply a Default Constructor It is possible to write a class with no constructors at all. If this is done, the system automatically provides an invisible default constructor. It is important to remember that as soon as the programmer writes any constructor for a class, then the system does not provide a default constructor. If a default constructor is needed, the programmer has to provide one.

44 44 12.5.4 Using super When Writing a Subclass Constructor with Parameters The example so far has made use of default construction. Default subclass construction relies on the existence of a default constructor in the superclass. Default initialization of instance variables, including inherited ones, is handled automatically. The example will now be extended to illustrate construction with parameters. Here is a constructor for the superclass, FoodV2, which takes a full set of parameters for its instance variables:

45 45 public FoodV2(String nameIn, double wholesaleCostIn, double markupIn) { name = nameIn; wholesaleCost = wholesaleCostIn; markup = markupIn; } Here is a correct constructor for the subclass, TaxedFoodV2, which takes a full set of parameters, including parameters for the inherited variables: public TaxedFoodV2(String nameIn, double wholesaleCostIn, double markupIn, double taxRateIn) { super(nameIn, wholesaleCostIn, markupIn); taxRate = taxRateIn; }

46 46 12.5.5 If You Use super, It has to be First; If You Don’t Use super, there has to be a Default Superclass Constructor When the system encounters a call to super() in a constructor, it looks for a constructor above the current class in the hierarchy. It will use the nearest constructor in the hierarchy above it which has a parameter list which matches the parameters used in the call. If you explicitly call super() in a subclass constructor, this call has to be the first line of code. If you don’t explicitly call super(), then you are relying on the default constructor in the superclass. Construction depends on cascading calls to constructors up through the inheritance hierarchy, whether the calls are explicit calls to super() or whether they are implicit calls which rely on the existence of a default constructor. The actual creation of a new object ultimately stems from a call to the constructor in the Object class. The constructors below that class are responsible for initializing the instance variables.

47 47 12.6 References to Classes and Subclasses in Programs and Methods

48 48 12.6.1 Class Hierarchies Have to Be Written from the Top Down When creating a hierarchy of classes, you have to work your way from the top down. The code for a subclass can only be compiled if its superclasses exist. The code for superclasses should also be tested before the subclass code is written. A test program at any level includes code that makes use of all constructors and methods in the class to make sure that they work correctly.

49 49 12.6.2 Superclass References to Subclass Objects are Valid. This is Done without Casting Syntactically, a reference to a subclass object can always be assigned to a reference that is declared to be of the type of any of the subclass’s superclasses. This is logically valid because instances of classes lower down in the hierarchy are “a kind of” the classes higher in the hierarchy. Syntactically, this idea can be illustrated as follows: FoodV2 myfood; TaxedFoodV2 mytaxedFood = new TaxedFoodV2(“bread”,.50,.05,.07); myfood = mytaxedFood;

50 50 12.6.3 Superclass References to Subclass Objects Don't Have Access to Methods Defined Only in the Subclass A superclass reference to a subclass object is distinctly limited, or has a distinct limitation. When working with a superclass reference, it is only possible to call methods defined in the superclass or methods inherited by the superclass. It is not possible to call methods on a superclass reference if the methods are only defined in the subclass.

51 51 12.6.4 It is Possible to Recover a Subclass Reference by Casting Casting can be used in order to recover the actual class that a superclass reference belongs to. The previous code example is repeated here with one line added. In the final line the TaxedFoodV2 reference is recovered from the FoodV2 reference: FoodV2 myfood; TaxedFoodV2 mytaxedFood = new TaxedFoodV2(“bread”,.50,.05,.07); myfood = mytaxedFood; TaxedFoodV2 newtaxedFood = (TaxedFoodV2) myfood;

52 52 12.6.5 Subclass References to Superclass Objects Are Not Valid Casting will not work if the type on the left is not the same type as the actual object on the right. Here is a gross example: /* NO! NO! NO! */ Ellipse2D.Double myellipse = new Ellipse2D.Double(10, 20, 30, 40); TaxedFoodV2 mytaxedFood = (TaxedFoodV2) myellipse;

53 53 This looks more plausible but is equally impossible: /* NO! NO! NO! */ FoodV2 myfood = new FoodV2(“cheese”, 1.25,.06); TaxedFoodV2 mytaxedFood = (TaxedFoodV2) myfood; Even though myfood and mytaxedFood are in the same inheritance hierarchy, myfood never was a taxed food. In general it is not valid to try and cast superclasses to subclasses because a superclass is not “a kind of” a subclass. Casting can recover the actual subclass of a superclass reference. It cannot recover a kind of reference that never existed.

54 54 12.6.6 The Keyword instanceof Checks Whether an Object is an Instance of a Given Class The keyword instanceof functions as an operator that returns a boolean value. It compares the actual type of a reference to a given class. This code fragment shows its use to permit a valid cast and prevent a mistaken one: if(myfood instanceof TaxedFoodV2) TaxedFoodV2 newtaxedFood = (TaxedFoodV2) myfood;

55 55 12.6.7 The Actual Parameter in a Method Call Can Be a Subclass of the Formal Parameter Type. Automatic Conversion to a Superclass Reference Occurs Reference type becomes critical when passing object references as parameters. A subclass object can always be assigned to a superclass reference. When a formal parameter is typed as a superclass reference in a method, it is permissible to pass a subclass object or reference as the actual, explicit parameter calling the method.

56 56 A new method, setMarkupToThisMarkup(), is given below. This method is defined in the FoodV3 class. The method is designed to set the markup of one food item to the markup already stored in another. This is accomplished by passing the other object as a parameter to the method. The parameter is typed FoodV3, the same as the class the method is defined in. public void setMarkupToThisMarkup(FoodV3 anotherFood) { double tempmarkup = anotherFood.getMarkup(); setMarkup(tempmarkup); }

57 57 Suppose the following code exists in a program that uses the food classes: TaxedFoodV3 mytaxedFood = new TaxedFoodV3(“bread”,.50,.05,.07); TaxedFoodV3 yourtaxedFood = new TaxedFoodV3(“milk”,.75,.08,.07); mytaxedFood.setMarkupToThisMarkup(yourtaxedFood); The third line of code is the critical one. The new method is inherited by the TaxedFoodV3 subclass, so making the call on mytaxedFood is possible. The actual, explicit parameter, yourtaxedFood, is an instance of TaxedFoodV3. In the method definition the formal parameter is typed FoodV3. In other situations where the actual parameter type did not agree with the formal parameter type, the compiler detected an error. However, in this case there is no problem. When passing a parameter, the actual parameter is assigned to the formal parameter. It is OK to assign a subclass object to a superclass reference without casting. The system knows that TaxedFoodV3 is a subclass of FoodV3, so when the actual parameter, a taxed food object, is passed, that reference is automatically converted to a FoodV3 superclass reference.

58 58 12.6.8 In the Body of a Method Definition, Method Calls Can Be Made on a Formal Parameter Which Is a Superclass Reference This line of code appears in the body of the method: double tempmarkup = anotherFood.getMarkup(); If the actual parameter is a subclass object, then anotherFood is a superclass reference. A superclass reference is distinctly limited. It is only possible to call methods defined in the superclass on such a reference. This does not raise a problem. The method getMarkup() is written in the FoodV3 class. Therefore it's possible to call it on a superclass reference to a subclass object. The TaxedFoodV3 class inherits this method. The version defined in the superclass is appropriate for the actual subclass object it’s called on. If the method being called were overridden, that would still be OK. How that works will be described in a later section.

59 59 12.6.9 Example Code (Showing All Changes up to this Point) public class FoodV3 { private String name; private double wholesaleCost; private double markup; public FoodV3(String nameIn, double wholesaleCostIn, double markupIn) { name = nameIn; wholesaleCost = wholesaleCostIn; markup = markupIn; } public void setName(String nameIn) { name = nameIn; } public String getName() { return name; }

60 60 public void setWholesaleCost(double wholesaleCostIn) { wholesaleCost = wholesaleCostIn; } public double getWholesaleCost() { return wholesaleCost; } public void setMarkup(double markupIn) { markup = markupIn; } public double getMarkup() { return markup; } public double getPrice() { return (wholesaleCost + wholesaleCost * markup); } public void setMarkupToThisMarkup(FoodV3 anotherfood) { double tempmarkup = anotherfood.getMarkup(); setMarkup(tempmarkup); }

61 61 public class TaxedFoodV3 extends FoodV3 { private double taxRate; public TaxedFoodV3(String nameIn, double wholesaleCostIn, double markupIn, double taxRateIn) { super(nameIn, wholesaleCostIn, markupIn); taxRate = taxRateIn; } public void setTaxRate(double taxRateIn) { taxRate = taxRateIn; } public double getTaxRate() { return taxRate; } public double getPrice() { double price; price = super.getPrice(); price = price + price * taxRate; return price; }


Download ppt "1 Object-Oriented Programming (Java), Unit 12 Kirk Scott."

Similar presentations


Ads by Google