2

I am learning how to use java to program, and am just learning about abstract classes and how they are useful. Say I have a class which extends another abstract class, which has 2 methods, one of which is abstract. My other, nonabstract class has 4 methods, two of which are the same as in the abstract class, and also defines the abstract method. When initializing my second object, my course tells me to use: (abstract class) foo = new (nonabstract class)(); My question, is that using this code prevents you from using the methods that have been added in the nonabstract class, and as a result, what is the advantage of using that code over (nonabstract class) foo = new (nonabstract class), which lets you use both the methods in the abstract class and the methods added in the nonabstract class. Thanks for the help in advance.

  • Why don't you go ahead and post the code you're describing. I'm finding it really difficult to visualize what you are saying without seeing the code. – Robert Harvey Mar 27 '15 at 4:43
3

Containers (lists, etc.) that are defined to hold objects of a certain base class can hold any object extended from that base class. There are many situations in software design where this functionality is useful. The base class may specify that certain behaviors are going to be required, but we may not know exactly how they should be implemented because it will be different depending on the characteristics of the new classes that extend from it.

To borrow from a very common example of polymorphism, in a drawing program, say you have three classes:

abstract class Shape {
    private Point position; 

    public Point getPosition(){ return position; }

    // Every Shape has an area, but we don't know
    // how to calculate it until we know what kind
    // of Shape it is. So this is defined, but it's
    // abstract.
    public abstract float getArea(); 
}

class Rectangle extends Shape {
    private float length;
    private float width;

    public float getArea(){ return length * width; }

    public float getLength(){ return length; }
    public float getWidth(){ return width; }
}

class Circle extends Shape {
    private float radius;

    public float getArea(){ return Math.PI * radius * radius; }

    public float getRadius(){ return radius; }
}

Now, in your code, you may have a container that holds Shape objects. They could be Circle or Rectangle objects. By defining your container in terms of the base class, you can now hold both subclasses safely, and you can call both getPosition() and getArea() on anything in the container.

List<Shape> shapes = new ArrayList<Shape>();
shapes.add(new Rectangle(5,10));
shapes.add(new Circle(5));

for (Shape s : shapes){
    s.getPosition();  // <-- this is OK
    s.getArea();      // <-- this is OK

    s.getRadius(); // <-- This produces a compiler error
    s.getWidth();  // <-- This produces a compiler error
}

Calling getRadius() or getWidth() on a Shape causes a compiler error, since Shape doesn't provide those methods. You would have to know more about the object and cast the object to the correct type before calling the more specific methods.

if (s instanceof Rectangle){
    ((Rectangle)s).getWidth();
}

if (s instanceof Circle){
    ((Circle)s).getRadius();
}

Note that this example specifically uses an abstract base class with inheritance, since there is something the base class can actually implement (the position). In the case where the base class is purely abstract, and does not provide any concrete implementation to be inherited by the sub-classes, you would probably define an interface, rather than a class. And the sub-classes would implement the interfaces.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.