Download Object Orientated Programming Lab 2

Survey
yes no Was this document useful for you?
   Thank you for your participation!

* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project

Document related concepts
no text concepts found
Transcript
ENIC4023 - Networked Embedded System Development
Object Oriented Programming Lab 2
Overview of Inheritance
A good PC can be bought for less than one months salary of a typical programmer. Thus in most projects
software costs tend to dominate. It is therefore important that applications are written in the most productive
way possible. Productivity can be much enhanced by code reuse and indeed all programming languages have
libraries of standard routines that can be used by application programmers. Java has extensive libraries of
classes that can be incorporated in your application; check out the Java API documentation for a list of these.
A big problem in reusing code from some existing library in your application is that it will often not do exactly
what you want. In procedural languages if you did not have access to the source code you either had to make do
with the non-ideal code or rewrite it completely. Even if you have the source code you have to make
modifications to someone else’s, often complex, code; an error prone activity.
One of the major advantages of object-orientated programming is that you can make modifications to existing
code without access to the source code and in a way that is much less prone to errors. This mechanism is known
as inheritance.
Inheritance means that instead of writing a class from scratch, you can start with some other class and extend it.
A class that is created via inheritance is called a subclass, and the class that is being inherited is known as a
superclass (or base class). Java has a root class called Object that is an implicit superclass of every other Java
class.
A subclass automatically inherits all of the non-private attributes and all of the non-private methods of its
superclass. Subclasses are not restricted solely to those features that they inherit; each subclass can declare
attributes and methods just like any other class. These new attributes and methods are combined with the
inherited attributes and methods to define the subclass.
A subclass is permited to override one or more superclass methods by including its own method(s) so long as
the overriding methods have identical names, scope modifiers, and parameter lists as the superclass method(s).
Within a subclass it is sometimes useful to be able to call the superclass version of a method, this is
accomplished by prefixing the method name with the reserved word super followed by a dot.
A subclass cannot override private methods, because it does not have access to superclass features that are
private. Also a subclass cannot alter the scope of an inherited method. However, if a method is public, then
every class has access to the method, ie every client class and every subclass. The protected scope allows
differentiation between client classes and subclasses. If an attribute or method is declared as protected it can be
accessed by subclasses but not by client classes. In class diagrams, protected attributes and methods are
preceded with a “#” symbol.
It is possible to have more than one subclass of the same superclass. However Java does not permit a subclass to
have more than one superclass. This restriction is known as single inheritance because each class can inherit
from at most one other class. Some languages, eg C++, allow multiple inheritance but this can lead to
complications.
Constructors are handled a bit differently than other methods in Java. Since each class must have a unique name,
it must also have its own constructor method(s). Java also prohibits a subclass from accessing its superclass
constructors by their original name. Java does though support a notation to permit the subclass to call any
constructor from its superclass. There are two restrictions:
(1)
The superclass constructor must be named with the reserved word super.
(2)
Such a call to a superclass constructor can be made only within constructor methods and only as their
first statement (subclass constructors should always include such calls to a superclass constructor).
Java instance variables are treated differently from methods when it comes to inheritance. Whereas methods
can be overridden to replace a superclass method, instance variables cannot be overridden. Unfortunately the
Java compiler does not generate errors when a subclass declares instance variables with the same name as a
superclass instance variable, two copies of the variable will be created. The new code of the subclass has access
to the subclass variable, and the inherited code from the superclass has access to the superclass variable. This is
an error-prone situation that is best avoided.
Example - Inheritance
Let's start by defining the class we want to inherit from; as an example we will use one which defines an
employee. Later on we will inherit from this class to define a subclass of it, eg one which defines a manager (a
particular type of employee). The class diagram and code for the Employee class are shown:
Employee
- String name
- double salary
- int hireYear
<<constructor>>
+ Employee(String, double, int)
<<query>>
+ void print()
+ int getHireYear()
<<update>>
+ void raiseSalary(double)
import java.util.*;
class Employee {
private String name;
private double salary;
private int hireYear;
public Employee(String n, double s, int y) {
name = n;
salary = s;
hireYear = y;
}
public void raiseSalary(double byPercent) {
salary *= 1 + byPercent / 100;
}
public void print() {
System.out.println(name + " " + salary + " " + hireYear);
}
public int getHireYear() {
return hireYear;
}
}
Obviously any class that you want to inherit from should be thorougly tested first to avoid propagation of bugs.
The code for a test class for the Employee class is shown. Edit, compile, and run this (obviously the Employee
class has to be compiled first).
public class testEmployee {
public static void main(String[] args) {
Employee burgerFlipper = new Employee("Joe Student", 2100, 1999);
burgerFlipper.print();
burgerFlipper.raiseSalary(2.1);
burgerFlipper.print();
}
}
OK, we now have a known good superclass from which to inherit. The subclass we are going to create is called
Manager. A class diagram is shown that shows the situation:
Employee
- String name
- double salary
- int hireYear
<<constructor>>
+ Employee(String, double, int)
<<query>>
+ void print()
+ int getHireYear()
<<update>>
+ void raiseSalary(double)
Manager
- String secretaryName
<<constructor>>
+ Manager(String, double, int)
<<query>>
+ String getSecretaryName()
<<update>>
+ void setSecretaryName(String)
+ void raiseSalary(double)
Note that the manager class adds a new attribute, two new methods and a constructor. The method raiseSalary is
overridden. The definition of the Manager class is shown; note especially that no knowledge of the Employee
class source code is needed to write this:
import java.util.*;
public class Manager extends Employee {
private String secretaryName;
public Manager(String n, double s, int y) {
super(n, s, y);
secretaryName = "";
}
public void setSecretaryName(String name) {
secretaryName = name;
}
public String getSecretaryName() {
return secretaryName;
}
public void raiseSalary(double byPercent) {
//add 1/10% bonus for every year of service
Calendar rightNow = new GregorianCalendar();
double bonus = 0.1 * (rightNow.get(Calendar.YEAR) - getHireYear());
super.raiseSalary(byPercent + bonus);
}
}
As well as inheriting from the Employee class, the Manager class uses the Calendar class from the java.util
package (look it up in the API docs). The Calendar class is simply used to get the current year as an integer; this
allows the hire year to be subtracted off to get the years of service for the bonus calculation.
The Manager class uses the getHireYear() method from the Employee class to get the value of the hireYear
attribute. It has to do this as it can't access the hireYear attribute directly as it is private to the Employee class. If
the scope of the hireYear attribute had been instead protected then the Manager class, as a subclass of Employee
could have accessed it directly.
A test class for the Manager class is shown, again, edit, compile, and run this to check that all performs as
expected:
public class testManager {
public static void main(String[] args) {
Manager sharpSuit = new Manager("Top Cat", 38500, 1998);
sharpSuit.print();
sharpSuit.raiseSalary(2.1);
sharpSuit.print();
}
}
Glossary of Some Object-Oriented Terminology
Inheritance Hierarchy - The process of inherited characteristics is cumulative. Each subclass inherits the
attributes and methods that are declared in the superclass, as well as all attributes and methods that may
have been inherited by the superclass. Think of the superclass as a parent class . This leads to the
notion of ancestor classes as the accumulation of parent, parent of the parent, parent of the parent of the
parent, and so on. Any Java class can be thought of as the accumulation of its own instance variables
and methods together with those inherited from its ancestors.
Type Conformance – An expression type conforms to its own class or any ancestor class, ie an expression can
be used anywhere that its type conforms to the required class type. Type conformance adds pliability to
methods – a method can be used with an object if the object is of the class of the method or of any
subclass (decendant) of the method’s class.
Dynamic Binding – The rules of type conformance allow a variable of one type to bind to an object of another
type so long as the object type conforms to the variable’s class. A variable can be assigned different
types of object at different times during a program’s execution. This ability of a variable to bind to
varying objects (including objects of varying type) is referred to as dynamic binding.
Polymorphism – The ability of a single variable (or parameter) to refer to objects of differing type is known as
subtype polymorphism or just polymorphism. Objects do not change the class to which they belong,
but a variable may be bound dynamically to different types of object. The behaviour of each object (ie
which methods are called) is determined by the object’s class, rather than the variables type. An object
is very much like the class to which it belongs. The object contains all attributes that are declared or
inherited by its class. Similarly, the object utilises the methods whose code comes from its class. This
connection between object and method is particularly important when overriding occurs, making
different versions of the same method available within the class hierarchy.
Extensibility - This refers to the ease with which software can be modified (extended) to solve problems other
than the initial intent.
Abstract Class – It is impossible to construct an object belonging to an abstract class. They are useful however,
since they can be used as the type for variables and parameters. Abstract classes can also be inherited,
and their protected and public attributes and methods are available for use by a subclass. An abstract
class can contain abstract methods; this is where the body of the method is left unspecified. If a class
contains an abstract method, then the class must be an abstract class. Classes are called concrete classes
unless they are declared to be abstract. Declaring a class to be abstract is done by inserting the word
abstract in front of the word class. Abstract classes can also include non-abstract methods that
are expected to be useful to subclasses. Think of an abstract class as a template with which to build
other classes through inheritance.
Exercise
Write a class that has a constructor that takes five integer arguments and a method that returns the sum of these.
Test this class by writing a simple test class that instantiates it. Now extend this class to include methods for
finding the maximum and minimum of the five values. (Hint: use protected scope for superclass attributes).