Java in a Nutshell, 5th Edition [Electronic resources] نسخه متنی

اینجــــا یک کتابخانه دیجیتالی است

با بیش از 100000 منبع الکترونیکی رایگان به زبان فارسی ، عربی و انگلیسی

Java in a Nutshell, 5th Edition [Electronic resources] - نسخه متنی

| نمايش فراداده ، افزودن یک نقد و بررسی
افزودن به کتابخانه شخصی
ارسال به دوستان
جستجو در متن کتاب
بیشتر
تنظیمات قلم

فونت

اندازه قلم

+ - پیش فرض

حالت نمایش

روز نیمروز شب
جستجو در لغت نامه
بیشتر
لیست موضوعات
توضیحات
افزودن یادداشت جدید


3.7. Abstract Classes and Methods


In Example 3-4,

we declared our
Circle class to be part of a package named
shapes. Suppose we plan to implement a number of
shape classes: Rectangle,
Square, Ellipse,
triangle, and so on. We can give these shape
classes our two basic area( ) and
circumference() methods. Now, to make it easy to
work with an array of shapes, it would be helpful if all our shape
classes had a common superclass, Shape. If we
structure our class hierarchy this way, every shape object,
regardless of the actual type of shape it represents, can be assigned
to variables, fields, or array elements of type
Shape. We want the Shape class
to encapsulate whatever features all our shapes have in common (e.g.,
the area() and circumference( )
methods). But our generic Shape class
doesn't represent any real kind of shape, so it
cannot define useful implementations of the methods. Java handles
this situation with

abstract methods .

Java
lets us define a method without implementing it by declaring the
method with the abstract modifier. An
abstract method has no body; it simply has a
signature definition followed by a semicolon.[8]
Here are the rules about abstract methods and the
abstract classes that contain them:

[8] An
abstract method in
Java is something like a pure virtual function in C++ (i.e., a
virtual function that is declared = 0). In C++, a
class that contains a pure virtual function is called an abstract
class and cannot be instantiated. The same is true of Java classes
that contain abstract methods.


  • Any class with an abstract method is automatically
    abstract itself and must be declared as such.

  • An abstract class cannot be instantiated.

  • A subclass of an abstract class can be
    instantiated only if it overrides each of the
    abstract methods of its superclass and provides an
    implementation (i.e., a method body) for all of them. Such a class is
    often called a

    concrete subclass, to emphasize the fact that
    it is not abstract.

  • If a subclass of an abstract class does not
    implement all the abstract methods it inherits,
    that subclass is itself abstract and must be
    declared as such.

  • static, private, and
    final methods cannot be
    abstract since these types of methods cannot be
    overridden by a subclass. Similarly, a final class
    cannot contain any abstract methods.

  • A class can be declared abstract even if it does
    not actually have any abstract methods. Declaring
    such a class abstract indicates that the
    implementation is somehow incomplete and is meant to serve as a
    superclass for one or more subclasses that complete the
    implementation. Such a class cannot be instantiated.


There is an important feature of the
rules of abstract methods. If we define the
Shape class to have abstract
area() and circumference( )
methods, any subclass of Shape is required to
provide implementations of these methods so that it can be
instantiated. In other words, every Shape object
is guaranteed to have implementations of these methods defined. Example 3-5 shows how this might work. It defines an
abstract Shape class and two
concrete subclasses of it.


Example 3-5. An abstract class and concrete subclasses

public abstract class Shape {
public abstract double area(); // Abstract methods: note
public abstract double circumference(); // semicolon instead of body.
}
class Circle extends Shape {
public static final double PI = 3.14159265358979323846;
protected double r; // Instance data
public Circle(double r) { this.r = r; } // Constructor
public double getRadius() { return r; } // Accessor
public double area() { return PI*r*r; } // Implementations of
public double circumference() { return 2*PI*r; } // abstract methods.
}
class Rectangle extends Shape {
protected double w, h; // Instance data
public Rectangle(double w, double h) { // Constructor
this.w = w; this.h = h;
}
public double getWidth() { return w; } // Accessor method
public double getHeight() { return h; } // Another accessor
public double area() { return w*h; } // Implementations of
public double circumference() { return 2*(w + h); } // abstract methods.
}

Each abstract method in Shape
has a semicolon right after its parentheses. They have no curly
braces, and no method body is defined. Using the classes defined in
Example 3-5, we can now write code such as:

Shape[] shapes = new Shape[3];          // Create an array to hold shapes
shapes[0] = new Circle(2.0); // Fill in the array
shapes[1] = new Rectangle(1.0, 3.0);
shapes[2] = new Rectangle(4.0, 2.0);
double total_area = 0;
for(int i = 0; i < shapes.length; i++)
total_area += shapes[i].area(); // Compute the area of the shapes

Notice two important points here:

  • Subclasses of Shape can be assigned to elements of
    an array of Shape. No cast is necessary. This is
    another example of a widening reference type conversion (discussed in
    Chapter 2).


  • You can invoke the
    area( ) and circumference()
    methods for any Shape object, even though the
    Shape class does not define a body for these
    methods. When you do this, the method to be invoked is found using
    dynamic method lookup, so the area of a circle is computed using the
    method defined by Circle, and the area of a
    rectangle is computed using the method defined by
    Rectangle.



/ 1191