wood burning stoves*
The moose likes Beginning Java and the fly likes inheritance Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of Murach's Java Servlets and JSP this week in the Servlets forum!
JavaRanch » Java Forums » Java » Beginning Java
Bookmark "inheritance" Watch "inheritance" New topic
Author

inheritance

mani maran
Greenhorn

Joined: Dec 29, 2000
Posts: 1
could u please explain about abstract class?
Patrick Lentz
Greenhorn

Joined: Oct 04, 2000
Posts: 23
Hmmm, how to explain this in short. I would advice to buy a book like Sams Teach Yourself Java 2 or something of the like (I think Sams has good beginners books). Anyways, back to that abstract class.
First of all, you cannot create an object from an abstract class. Why not? Because an abstract class has at least one method in it that is abstract, in other words it has no implementation. An abstract method has a name followed by a semicolon and no implementation.
So,it's really easy to make an abstract class..all you need to do is for instance ad an abstract method and this automactically makes the whole class abstract.
What would this be usefull for?
Well, let's say you have an abstract class Shape. It has some methods with implementation, but also an abstract method Draw.
Now you make a couple of classes that extend themselves from Shape, namely Circle and Triangle. Since they inheritd all the methods from Shape, you make sure this way that they both have the method Draw, but they both need to implement the method themselve. In other words you need to make them concrete by writing code inside the Draw method for these classes. And for a Circle drawing itself this would be different than when you want a Triangle to draw itself.
So, the main use....to make sure that classes that are inherited from the abstract classes will know methods that are in the abstract class (and which have their own implementation).
Hope this makes things a bit clearer. Good luck
Patrick
Sean MacLean
author
Ranch Hand

Joined: Nov 07, 2000
Posts: 621
An abstract class is a class that (ussually) contains an abstract method. An abstract class cannot be instantiated so it only becomes useful when you extend it with another class. So we have an abstract class with an abstract method and a class that extends the abtract class. The class that extends the abstract class must define the abstract method. Therefore, if you have a bunch of classes in which you want to have a particular method included, then create an abstract super class that contains the method as a abstract method and then have all the other classes extend this class. The result of doing this has another benefit. If you have several types of classes that are related (say in a list) and you want to process them, you can cast them to the super (abstract) class and then call the abstract method. Since all of the sub classes must implement this method, then you know that it must be available.
Often this type of thing is done using an interface because once you extend your custom abstract class you cannot extend any other classes. You can, however, implement interfaces until the cows come home. Have a look a this Java Ranch tutorial for a discussion on this. I hope this gives you a bit of a head start on abstract classes
Sean
Jacquie Barker
author
Ranch Hand

Joined: Dec 20, 2000
Posts: 201
Here's a passage from my book, Beginning Java Objects, which explains abstract classes (taken from Chapter 7 - copyright 2000 Jacquie Barker) - I hope it helps!
(Unfortunately, when I pasted in the excerpt from the book, the indentation of all code examples was lost ...)
Abstract Classes
We learned in Chapter 5 how useful it can be to consolidate shared features - attributes and methods - of two or more classes into a common superclass, a process known as generalization. We did this when we created the Person class as a generalization of Student and Professor and then moved the declarations of all of their common attributes (name, address, birthdate) and methods (the 'get' and 'set' methods for each of the shared attributes) into this superclass. By doing so, the Student and Professor subclasses both became simpler, and we eliminated a lot of redundancy that would otherwise have made maintenance of the SRS much more cumbersome.
There is one potential dilemma to be dealt with when creating a superclass after the fact: if all of the classes that are to be subclasses of this new superclass happen to have defined methods with the same signature, but with different logic, which version of the method, if any, should be propagated up to the parent? Let's use a specific example: say that long before it occurred to us to create a Person superclass, a requirement arose to devise a method for both the Student and Professor classes to compute their respective monthly salaries (we are assuming that students work for the university as teaching assistants or as research fellows). We decided that the signature of this method would be as follows:
public float computePaycheck(int hoursWorked);

o In the case of a professor, his/her salary is based on the number of hours worked in a given month multiplied by an hourly wage.
o In the case of a student, his/her salary is a fixed monthly stipend, but is only paid if the student worked more than a certain minimum number of hours during the month.
We then implemented the computePaycheck() methods for these two classes, the code or which is shown below:
class Professor {
String name;
String ssn;
float hourlySalary;
// etc.
// Get/set methods omitted ...
public float computePaycheck(int hoursWorked) {
return hoursWorked * hourlySalary;
}
}
class Student {
String name;
String ssn;
float monthlyStipend;
int minimumRequiredHours;
// etc.
// Get/set methods omitted ...
// Same signature as for the Professor class, but different
// internal logic.
public float computePaycheck(int hoursWorked) {
if (hoursWorked > minimumRequiredHours)
return monthlyStipend;
else return 0.0;
}
}
At some later point in time, we decide to generalize these two classes into a common superclass called Person. We can easily move the common attributes (name, ssn) and their get/set methods out of Student and Professor and into Person, but what should we do about the computePaycheck() method?
o We could provide a generic computePaycheck() method with the same exact signature in Person, and then allow the Professor and Student classes' specialized versions of the method to effectively override it. But, this raises the question, why even bother to code the internal processing details of a computePaycheck() method in Person if both Student and Professor have already in essence overridden it? The answer to this question depends on whether you plan on instantiating the Person class directly. That is,
o If you plan on creating objects of generic type Person in your application - objects which are neither Students nor Professors - then the Person class may indeed need a computePaycheck() method of its own, to perform some sort of generic paycheck computation.
q On the other hand, if you only plan on instantiating the Student and Professor classes, then going to the trouble of programming the internal processing details of a method for Person that will never get used does indeed seems like a waste of time.
o If we know that we are not going to instantiate Person objects, then another option would be to leave the computePaycheck() method out of the Person class entirely. Both Student and Professor would then be adding this method as a new feature above and beyond what they inherit from Person, versus inheriting and overriding the method. The shortcoming of this approach is that we lose the ability to guarantee that all future Person objects will understand the message for computing their paychecks. If another subclass of Person is created in the future (say, AdministrativeStaffMember), and the designer of that class isn't aware of the need to provide for a computePaycheck() method, then we'll wind up with a situation where some Person objects will understand a message like:
p.computePaycheck(40);
and others will not. We'll therefore lose the advantage of polymorphism: namely, being able to create a collection of all different types of Person objects, and to iterate through it to compute their paychecks, because even though an AdministrativeStaffMember is a Person, it doesn't know how to respond to a request to perform this service.
Before we try to make a final decision on how to approach the computePaycheck() method, let's consider a different set of circumstances.
The preceding example explored a situation where the need for generalization arose after the fact; now let's look at this problem from the opposite perspective. Say that we have the foresight to know that we are going to need various types of Course objects in our SRS: lecture courses, lab courses, independent study courses, etc. So, we want to start out on the right foot by designing the Course (super)class to be as versatile as possible to facilitate future specialization.
We might determine up front that all Courses, regardless of type, are going to need to share a few common attributes:
String courseName;
String courseNumber;
int creditValue;
CollectionType enrolledStudents;
Professor instructor;
as well as a few common behaviors:
establishCourseSchedule()
enrollStudent()
assignProfessor()
Some of these behaviors may be generic enough so that we can afford to program them in detail for the Course class, knowing that it is a pretty safe bet that any future subclasses of Course will inherit these methods 'as is' without needing to override them:
class Course {
String courseName;
String courseNumber;
int creditValue;
Collection enrolledStudents;
Professor instructor;
// Get/set methods omitted ...
public boolean enrollStudent(Student s) {
if (we haven't exceeded the maximum allowed enrollment)
enrolledStudents.add (s);
}
public void assignInstructor(Professor p) {
instructor = p;
}
}
However, other of the behaviors may be too specialized to enable us to come up with a useful generic version. For example, the rules governing how to schedule class meetings may be class-specific:
o A lecture course may only meet once a week for 3 hours at a time;
o A lab course may meet twice a week for 2 hours each time; and
o An independent study course may meet on a custom schedule agreed to by a given student and professor.
So, it would be a waste of time for us to bother trying to program a generic version of the establishCourseSchedule() method at this point in time. And yet we know that we'll need such a method to be programmed for all subclasses of Course that get created down the road. How do we communicate the requirement for such a behavior in all subclasses of Course and, more importantly, enforce its future implementation?
OO languages such as Java come to the rescue with the concept of abstract classes. An abstract class is used to enumerate the required behaviors of a class without having to provide an explicit implementation of each and every such behavior. We program an abstract class in much the same way that we program a regular class, with one exception: for those behaviors for which we cannot (or care not to) devise a generic implementation - e.g., the establishCourseSchedule() method in our preceding example - we are allowed to specify method signatures without having to program the method bodies. We refer to a 'codeless', or signature-only, method specification as an abstract method.
Beginners often confuse the term 'abstract class' with 'abstract data type' because the terms sound the same. But, ALL classes - abstract or not - are abstract data types, whereas only certain classes are abstract classes.
So, we can go back to our Course class definition, and add an abstract method as highlighted below:
class Course {
String courseName;
String courseNumber;
int creditValue;
CollectionType enrolledStudents = new CollectionType ();
Professor instructor;
public boolean enrollStudent(Student s) {
if (we haven't exceeded the maximum allowed enrollment)
enrolledStudents.add(s);
}
public void assignInstructor(Professor p) {
instructor = p;
}
// Note the use of the 'abstract' keyword.
public abstract void establishCourseSchedule (String
startDate, String endDate);
}
Note that the establishCourseSchedule() method signature has no curly braces following the closing parenthesis of the argument list. Instead, the signature ends with a semicolon ( - that is, it is missing its 'body', which normally contains the detailed logic of how the method is to be performed. The method signature is explicitly labeled as 'abstract', to notify the compiler that we didn't accidentally forget to program this method, but rather that we knew what we were doing when we intentionally omitted the body.
By specifying an abstract method, we have:
o Specified a service that objects belonging to this class (or one of its subclasses) must be able to perform;
o Detailed the means by which we will ask them to perform this service by providing a method signature, which as we learned in Chapter 4 controls the format of the message that we will pass to such objects when we want them to perform the service; and
o Facilitated polymorphism - at least with respect to a certain method - by ensuring that all subclasses of Course will indeed recognize a message associated with this method.
However, we have done so without pinpointing the private details of how the method will accomplish this behavior. That is, we've specified 'what' an object belonging to this class needs to be able to do without pinning down 'how' it is to be done.
Whenever a class contains one or more abstract methods, then the class as a whole is considered to be an abstract class. In Java, we designate that a class is abstract with the keyword 'abstract':
abstract class Course {
// details omitted
}
It isn't necessary for all methods in an abstract class to be abstract; an abstract class can also contain 'normal' methods that have both a signature and a body, known as concrete methods.
Abstract Classes and Instantiation
There is one caveat with respect to abstract classes: they cannot be instantiated. That is, if we define Course to be an abstract class in the SRS, then we cannot ever instantiate generic Course objects in our application. This makes intuitive sense:
o If we could create an object of type Course, it would then be expected to know how to respond to a message to establish a course schedule, because the Course class defines a method signature for this behavior.
o But because there is no code behind that method signature, the Course object would not know how to behave in response to such a message.
The compiler comes to our assistance by preventing us from even writing code to instantiate an abstract object in the first place; if we were to try to compile the following code snippet:
Course c = new Course(); // Impossible! The compiler will
// generate an error
// on this line of code.
// details omitted ...
// Behavior undefined!
c.establishCourseSchedule('01/10/2001', '05/15/2001');

we'd get the following compilation error on the first line:
class Course is an abstract class. It can't be instantiated.
While we are indeed prevented from instantiating an abstract class, we are nonetheless permitted to declare reference variables to be of an abstract type:
Course x; // This is OK.
x = new Course(); // Error - Course is an abstract class!
Why would we even want to declare reference variables of type Course in the first place if we can't instantiate objects of type Course? It has to do with supporting polymorphism; we'll learn the importance of being able to define reference variables of an abstract type when we talk about Java collections in depth in Chapter 13.
Inheritance and Abstract Classes
An abstract class may be extended to create subclasses, in the same way that a 'normal' class can be extended. Having intentionally created Course as an abstract class to serve as a common 'template' for all of the various course types we envision needing for the SRS, we may later derive subclasses LectureCourse, LabCourse, and IndependentStudyCourse. Unless a subclass overrides all of the abstract methods of its abstract superclass with concrete methods, however, it will automatically be considered abstract, as well. That is, a subclass of an abstract class must provide an implementation for all inherited abstract methods in order to 'break the spell' of being abstract.
In the following code snippet, we show these three subclasses of Course; of these, only two - LectureCourse and LabCourse - provide implementations of the establishCourseSchedule() method, and so the third subclass - IndependentStudyCourse - remains an abstract class and hence cannot be instantiated.
class LectureCourse extends Course {
// All attributes are inherited from the Course class;
// no new attributes are
// added.
public void establishCourseSchedule (String startDate,
String endDate) {
// Logic would be provided here for how a lecture course
// establishes a course schedule; details omitted ...
}
}
class LabCourse extends Course {
// All attributes are inherited from the Course class; no
// new attributes are
// added.
public void establishCourseSchedule (String startDate,
String endDate) {
// Logic would be provided here for how a lab course
// establishes a
// course schedule; details omitted ...
}
}
class IndependentStudyCourse extends Course {
// All attributes are inherited from the Course class;
// no new attributes are
// added, and we don't override the establishCourseSchedule()
// method in this subclass, either.
}
If we were to try to compile the above code, the Java compiler would force us to flag the IndependentStudyCourse class with the keyword 'abstract'; that is, we'd get the following compilation error:
Class IndependentStudyCourse must be declared abstract. It does not define void establishCourseSchedule (String, String) from class Course.
We've just hit upon how abstract methods serve to enforce implementation requirements! Declaring an abstract method in a superclass ultimately forces all derived subclasses to provide class-specific implementations of the abstract methods; otherwise, the subclasses cannot be instantiated.

------------------
author of:
Beginning Java Objects
[This message has been edited by Jacquie Barker (edited January 01, 2001).]


Author of Beginning Java Objects, Beginning C# Objects, and Taming the Technology Tidal Wave
Peter Tran
Bartender

Joined: Jan 02, 2001
Posts: 783
Jacquie Barker does a great job explaining your initial question regarding "abstract classes." One thing I found missing in all the replies are the difference between an interface and an abstract class. Personally, I think it's important to be able to determine during design when one should choose to use an interface vs an abstract class.
I won't go over an abstract class again, because Jacquie reply is more than adequate.
An interface is very similar to an abstract class. From the Java Tutorial, "A Java interface defines a set of methods but does not implement them. A class that implements the interface agrees to implement all of the methods defined in the interface, thereby agreeing to certain behavior." See, http://java.sun.com/docs/books/tutorial/java/interpack/interfaceDef.html

The thing you have to remember, is that no implementation is provided at all for any of the methods in an interface. An interface just provides method signatures. Furthermore, any instance reference are required to be constants. This is done by declaring them "final static."
E.g. public final static double PI=3.14.
Why then would you want to use an interface rather than an abstract class?
1. JAVA only allows single inheritance, so you can't extend from multiple abstract class. You can however, implement as many interfaces as you want.
Should you then make everything an interface?
2. No. Only use interface when it makes sense to do so. If you have a legitimate design calling for an abstract class, then use one. My rule of thumb is always asking myself, is there an "is-a" relationship between my classes. If yes, then I use an abstract class. For example (borrowing from Jacquie example), "is-a" Student a Person? "is-a" Professor a Person? (Sometime I answer "no" for the last question. :-))
3. Use an interface when you have methods that you want a class to implement. This is really useful for cases where you hava a collection of classes, but you don't know the detail of the implementation. Here's a contrived example,
interface IChildren {
public void printChildren();
};
class People implements IChildren {
public void printChildren() {
System.out.println("One per year.");
}
};
class Rabbit implements IChildren {
public void printChildren() {
System.out.println("Many per year.");
}
};
public class ContrivedExample {
public static void main(String[] argv) {
java.util.List list = new java.util.ArrayList();
list.add(new People());
list.add(new Rabbit());
// We can enumrate through the list, and not worry
// about the actual class type if we use the interface.
for (int i = 0; i < list.size(); ++i) {
IChildren Obj = (IChildren)list.get(i);
Obj.printChildren();
}
}
};
In summary, use an interface for the following reasons (again borrowed from the JAVA Tutorial):
* Capturing similarities between unrelated classes without artificially forcing a class relationship. See above example, there are no similarities between class People and class Rabbit.
* Declaring methods that one or more classes are expected to implement.
 
It is sorta covered in the JavaRanch Style Guide.
 
subject: inheritance