Survey
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
Week 3: Object-Oriented Programming - Inheritance (Read Ch.13 in Horstmann, Ch.7 in Lewis&Loftus 2nd ed., Ch.9 in Deitel&Deitel 3rd ed.) Code reuse is important in software engineering and inheritance is one way to do it. - Inheritance allows to define a class that is similar to an existing class - it just adds a few new attributes or methods, or implements existing methods differently - OOP supports declaring the new class as a subclass, which extends the old class - the subclass inherits all the attributes and methods of the original class - it can add new ones, as well as override the implementation of existing methods Example: A hierarchy of related classes: The class Undergrad is a subclass (or specialization) of Student. Inversely, we say that Student is a superclass (or generalization) of Undergrad. class Student { // instance attributes private String name; private long number; //constructor public Student(String aName, long aNumber){ name = aName; number = aNumber; } // instance methods public void setName(String aName){ name = aName; } public String getName(){ return name; } public void setNumber(long aNumber){ number = aNumber; } public long getNumber(){ return number; } public String toString(){ return "Student[name=" + name + ",number=" + number + "]"; } } class Undergrad extends Student{ // instance attributes ( name and number are inherited from Student) private String major; private int year; // instance methods setName, getName, setNumber, & getNumbers are inherited from Student //constructor public Undergrad(String aName, long aNumber, String aMajor, int aYear){ super (aName, aNumber); setMajor (aMajor); setYear(aYear); } // new methods public void setMajor(String aMajor){ major = aMajor; } public String getMajor(){ return major; } public void setYear(int aYear){ year = aYear; } public int getYear(){ return year; } // overriding the base class toString() // note that private base class attributes are not available in the subclass public String toString(){ return "Undergrad[name=" + getName() + ",number=" + getNumber() + " ,major=" + major + ",year=" + year + "]"; } } public class Inh1 { public static void main(String[] args){ Student s1 = new Student("John",202123456); System.out.println("s1 is " + s1.getName()); System.out.println(s1.toString()); Undergrad s2 = new Undergrad("Mary",201234567,"ITEC",1); System.out.println("s2 is "+s2.getName()); //inherited s2.setName("Mary Ellen"); //inherited System.out.println("s2 is in year " + s2.getYear()); //new method System.out.println(s2.toString()); } } Note: Every instance of a class is also an instance of all it superclasses (similar to sets). So an instance of Undergrad is also an instance of Student (ie s2 is also a Student object). Note: Another implementation of the subclass method toString(), which uses the base class toString(): public String toString(){ // call superclass’s method String s = super.toString(); // make appropriate changes & return s = s.substring(s.indexOf("["),s.length()-1); return "Undergrad" + s + ",major=" + major + ",year=" + year + "]"; } Inheritance class architecture Student Undergrad Postgrad Other examples of “is a” type relationship: BankAccount Person Employee CheckingAccount SavingsAccount Programmer Sometimes inheritance means just expanding information and the “is a” meaning is not suitable. Ex. Point <- Circle <- Cylinder. Overloaded vs Overridden Methods It is important to distinguish between overloaded and overridden methods. Overloading - you are defining several methods with the same name that will be available in the same class. this is only possible when the signatures of the methods are different. Overwriting - overridden methods have the same signature. the method in the subclass replaces that in the superclass the superclass’s version is still available using super public class Parent { public void meth() // #1 { ... } public void meth(int n) // #2, overloads #1 { ... } ... } public class Offspring extends Parent { public void meth(int n) // #3, overrides #2 { ... } ... } ... // in main Parent o1 = new Parent(); Offspring o2 = new Offspring(); o1.meth(); // calls #1 o1.meth(31); // calls #2 o2.meth(); // calls #1 o2.meth(29); // calls #3 Inheritance and Attributes - - attributes defined in a super-class are inherited by the subclass, but are not directly accessible (assuming they are private) they can only be accessed through inherited public methods if you redefine an attribute in the subclass, the new attribute does not replace the original one, as they are stored in different memory areas the subclass attribute will shadow the one defined in the superclass the use of protected instead of private for the superclass attributes allows the derived classes to directly access those attributes (no need to use methods to access them). if the superclass’s attribute is protected, and there is another derived class attribute with the same name (bad idea !), you can refer to the base class attribute as super.attribute. public class Parent{ ... public setAtt(int n){ att = n; } private int att; } public class Offspring extends Parent{ public void meth(){ att = 4; // sets Offspring’s att setAtt(3);// sets Parent’s att } private int att; } // in main Offspring o = new Offspring(); o.meth(); Constructors and Inheritance - an instance of a class C in a hierarchy is also an instance of all of C’s superclasses (all the way to the top). Therefore when you call the constructor of C you have to call the constructors of all of C’s superclasses You can call a constructor of C’s superclass by putting super(...) in C’s constructor If you leave out the call to the superclass’s constructor, Java automatically inserts super() at the beginning of the subclass’s constructor, i.e. a call to the superclass’s 0 arguments constructor, that initializes the attributes to default values, 0 for numbers, false for boolean, and null for objects. public class Student{ public Student() { name = "UNKNOWN"; number = -1; } public Student(String aName, long aNumber){ name = aName; number = aNumber; } ... private String name; private long number; } public class Undergrad extends Student{ public Undergrad(){ super();// calls Student’s 0 args constructor major = "general"; year = 1; } public Undergrad(String aName, long aNumber, String aMajor, int aYear){ super(aName, aNumber);// calls Student’s 2 args constructor major = aMajor; year = aYear; } ... private String major; private int year; } // in main Undergrad u = new Undergrad("John", 201234567, "ITEC", 1); If there are more than one constructor, each ancestor class’s constructor is called in turn. Ex.: public class PartTimeUndergrad extends Undergrad{ //constructors public PartTimeUndergrad(){ super();// calls Undergrad’s 0 args constructor courseLoad = 2.5; } public PartTimeUndergrad(String aName, long aNumber, String aMajor, int aYear, double aLoad) { super(aName, aNumber, aMajor, aYear); // calls Undergrad’s 4 args constructor courseLoad = aLoad; } ... private double courseLoad; } // in main PartTimeUndergrad p = new PartTimeUndergrad("John", 201234567, "ITEC", 1, 3.5); Ex.2.5 Define a method public double calculateFees(double courseload) for Student and Undergrad which returns the fees to be paid by the student depending on his/her courseload. Suppose that for students generally, the fees are $800 per course and that for undergraduates, there is an additional incidental charge of $100 for first year students and $150 for students in later years. public class Student{ ... public double calculateFees(double courseload){ final double FEE_PER_COURSE = 800; return FEE_PER_COURSE * courseload; } ... } public class Undergrad extends Student{ ... // override Student’s calculateFees method public double calculateFees(double courseload){ final double INCIDENTAL_FEE_Y1 = 100; final double INCIDENTAL_FEE_Y_GT_1 = 150; double fee = super.calculateFees(courseload); if (year == 1) fee = fee + INCIDENTAL_FEE_Y1; else fee = fee + INCIDENTAL_FEE_Y_GT_1; return fee; } ... } // in main Student s = new Student("Mary", 202345678); York.println(s + " fees: " + s.calculateFees(4.5)); Undergrad u = new Undergrad("John", 201234567, "ITEC", 1); York.println(u + " fees: " + u.calculateFees(4.5)); Student s1=u; // this will not COPY an object; it will just create another reference to the same object An Undergrad object “is a” Student object too. This why s1 can point to the object u; however s1 will see only the Student part of u. You cannot do the same thing between unrelated classes. The Cosmic Superclass - All classes in Java ultimately inherit from the Object class. - All new classes are part of Sun’s object hierarchy. - The Object class contains the following methods: String toString(), equals(Object obj), Object clone() - You can use the Object methods or, better, overwrite them in your classes The following code can be used with any object s: s1=s.clone(); if (s1.equals(s)) York.println(“The two objects are identical”); Final Methods - In writing classes one has to keep in mind that future applications might be extending them through inheritance. In this sense one has to think on whether to declare base class variables protected instead of private. As far as the methods are concerned base class methods can be overridden by derived class methods (having the same signature). - Occasionally a base class method MUST be used always with the same code and programmers can enforce it by using the modifier final in front of that base class method declaration. Abstract Classes - An abstract class represents a generic concept in the class hierarchy. It cannot be instantiated and it might contain one or more abstract methods, which have no definition. Both class and abstract methods declarations must have the abstract modifier in front. Note that a static or final method cannot be also abstract. Ex. Vehicle can be made an abstract class as it is too generic for applications. Car, Boat and Plane can be derived from Vehicle. Vehicle might contain just the variable speed and the method fuelConsumption() could be abstract, with implementations only in the derived classes. More about abstract classes when we discuss interfaces. Graphics (Read ch.4 in Horstmann, ch.9 in Lewis & Loftus and ch.11 in Deitel&Deitel) Using JOptionPane methods gave you a first glimpse at what Java has to offer in terms of user interface. The JOptionPane boxes were created on top of the black screen. Automatically they provided an “OK” button which closed them. Later we shall discuss much more Graphics User Interface (GUI) techniques. Most of the GUI classes are provided in Java by the Abstract Windowing Tools (AWT) package (java.awt). With the arrival of the Java 2 platform AWT was expanded with the Swing classes (java.swing). Swing classes provide alternative components that have more functionality than AWT and therefore we shall prefer to use Swing. With graphics one can easily draw shapes, one can control colors and fonts, one can organize the screen in a user-friendly way. One of Java’s initial appeals was its support for GUI. Unlike in other OOP languages (such as C++), building an appealing GUI in Java is a relatively easy task. This is also because of the Java class hierarchy architecture which includes GUI classes. Classes of AWT such Color, Font, Graphics, Component are derived from the Object superclass. The Graphics Class Graphics is an abstract class (i.e.you cannot instantiate Graphics objects). This is because graphics is performed differently on different platforms (e.g. compare a PC with a Mac, or a mainframe). When Java is implemented on a specific platform a derived Graphics class is automatically created but its implementation is hidden from us inside that derived class. In our applications we shall only use references to derived class Graphics objects (typically we shall call them g, although you can use other names) . The Component Class Component is a superclass for many of the classes in AWT. Its method paint() takes a Graphics object as an argument: public void paint (Graphics g) . Various derived classes from Component will overwrite paint() to perform various graphics operations with the help of the g Graphics object passes as a parameter. A JFrame Example To illustrate the creation of graphics in a Java application, the example below will utilize a JFrame object, which is a common way to create GUI in stand-alone Java applications. import java.awt.*; import java.awt.event.*; // Java extension packages import javax.swing.*; public class ShowColors extends JFrame { // constructor sets window's title bar string and dimensions public ShowColors() { super( "Using colors" ); // this will put a title on the frame bar setSize( 400, 130 ); // size in pixels show(); } // draw rectangles and Strings in different colors public void paint( Graphics g ) { // call superclass's paint method super.paint( g ); // setColor, fillRect, drawstring, getColor, getRed etc are methods of Graphics g.setColor( new Color( 255, 0, 0 ) ); // set new drawing color using integers for R/G/B g.fillRect( 25, 25, 100, 20 ); g.drawString( "Current RGB: " + g.getColor(), 130, 40 ); // set new drawing color using floats g.setColor( new Color( 0.0f, 1.0f, 0.0f ) ); g.fillRect( 25, 50, 100, 20 ); g.drawString( "Current RGB: " + g.getColor(), 130, 65 ); // set new drawing color using static Color objects g.setColor( Color.blue ); g.fillRect( 25, 75, 100, 20 ); g.drawString( "Current RGB: " + g.getColor(), 130, 90 ); // display individual RGB values Color color = Color.magenta; g.setColor( color ); g.fillRect( 25, 100, 100, 20 ); g.drawString( "RGB values: " + color.getRed() + ", " + color.getGreen() + ", " + color.getBlue(), 130, 115 ); } // execute application public static void main( String args[] ) { ShowColors application = new ShowColors(); application.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE ); } } // end class ShowColors Important Notes: The driver class defines in main() an object of the driver class type. The driver creates an object but does not call paint(). Class JFrame has this call built in. The only thing that is left for the driver is to provide the (optional) JFrame closing procedure. Positioning on a JFrame is relative to the top left corner and it is measured in pixels (picture elements of a size which can be set by the workstation user). Colors can be specified either through integer values (0-255) of the Red, Green and Blue components (primary colors), or through float values (the sum of the 3 floats must be equal to 1). Setting the color will affect all Graphics operations (fillRect and drawstring). Same Example as a JApplet An alternative to JFrame is JApplet, another class part of Swing which inherits from Component. The difference with JApplet is not only in its programming but also in the fact that it can be executed not as a stand-alone application but as an applet by any Web browser. Here is the same code as an applet: Ex.3.4 ShowColors.java written as an applet import java.awt.*; import java.awt.event.*; import javax.swing.*; public class ShowColors extends JApplet { public void paint( Graphics g ) { // call superclass's paint method super.paint( g ); // set new drawing color using integers g.setColor( new Color( 255, 0, 0 ) ); g.fillRect( 25, 25, 100, 20 ); g.drawString( "Current RGB: " + g.getColor(), 130, 40 ); // set new drawing color using floats g.setColor( new Color( 0.0f, 1.0f, 0.0f ) ); g.fillRect( 25, 50, 100, 20 ); g.drawString( "Current RGB: " + g.getColor(), 130, 65 ); // set new drawing color using static Color objects g.setColor( Color.blue ); g.fillRect( 25, 75, 100, 20 ); g.drawString( "Current RGB: " + g.getColor(), 130, 90 ); // display individual RGB values Color color = Color.magenta; g.setColor( color ); g.fillRect( 25, 100, 100, 20 ); g.drawString( "RGB values: " + color.getRed() + ", " + color.getGreen() + ", " + color.getBlue(), 130, 115 ); } } // end class ShowColors Important Notes: The use of JApplet is even simpler than with JFrame. You do not need to create an object and the closing of the applet window. Like with JFrame, JApplet automatically calls paint(). Another important difference between applets and frames is that the sizing and the baptizing of the window is done in HTML instead of Java. What was done through the constructor of the JFrame object is done for applets through the HTML code: // this is the file ShowColors.html <html> <applet code = "ShowColors.class" width = "400" height = "130"> </applet> </html>