How to Instantiate an Abstract Class Directly

Can we instantiate an abstract class?

Here, i'm creating instance of my class

No, you are not creating the instance of your abstract class here. Rather you are creating an instance of an anonymous subclass of your abstract class. And then you are invoking the method on your abstract class reference pointing to subclass object.

This behaviour is clearly listed in JLS - Section # 15.9.1: -

If the class instance creation expression ends in a class body, then
the class being instantiated is an anonymous class. Then:

  • If T denotes a class, then an anonymous direct subclass of the class named by T is declared. It is a compile-time error if the
    class denoted by T is a final class.
  • If T denotes an interface, then an anonymous direct subclass of Object that implements the interface named by T is declared.
  • In either case, the body of the subclass is the ClassBody given in the class instance creation expression.
  • The class being instantiated is the anonymous subclass.

Emphasis mine.

Also, in JLS - Section # 12.5, you can read about the Object Creation Process. I'll quote one statement from that here: -

Whenever a new class instance is created, memory space is allocated
for it with room for all the instance variables declared in the class
type and all the instance variables declared in each superclass of the
class type, including all the instance variables that may be hidden.

Just before a reference to the newly created object is returned as the
result, the indicated constructor is processed to initialize the new
object using the following procedure:

You can read about the complete procedure on the link I provided.


To practically see that the class being instantiated is an Anonymous SubClass, you just need to compile both your classes. Suppose you put those classes in two different files:

My.java:

abstract class My {
public void myMethod() {
System.out.print("Abstract");
}
}

Poly.java:

class Poly extends My {
public static void main(String a[]) {
My m = new My() {};
m.myMethod();
}
}

Now, compile both your source files:

javac My.java Poly.java

Now in the directory where you compiled the source code, you will see the following class files:

My.class
Poly$1.class // Class file corresponding to anonymous subclass
Poly.class

See that class - Poly$1.class. It's the class file created by the compiler corresponding to the anonymous subclass you instantiated using the below code:

new My() {};

So, it's clear that there is a different class being instantiated. It's just that, that class is given a name only after compilation by the compiler.

In general, all the anonymous subclasses in your class will be named in this fashion:

Poly$1.class, Poly$2.class, Poly$3.class, ... so on

Those numbers denote the order in which those anonymous classes appear in the enclosing class.

How to instantiate an abstract class in Java?

You cannot directly create an instance of an abstract class. You must first define a class that extends the abstract class and then create an instance of that class.

e.g.

public ConcreteEmployeeFileProcessor extends EmployeeFileProcessor {

}

You can then create instances of ConcreteEmployeeFileProcessor but reference it using the abstract type.

EmployeeFileProcessor instance = new ConcreteEmployeeFileProcessor();

instantiating an abstract class in JAVA?

An abstract class should be something that doesn't make sense if it exists completely on its own.

Take a Vehicle for example. Can you describe a Vehicle without describing a specific type of Vehicle at the same time? No - because Vehicle is just a way of describing common features and behaviours of a group of related objects. Alternatively, you could think of them as concepts.

Your quote:

Simply, in a good object oriented program, you should never want to instantiate an abstract class or interface. If you do, the design is probably wrong.

Is spot on. If you've written an abstract class that you want to instantiate completely on its own, then it isn't an abstract class. If you ever find yourself in this situation, you probably need to carry out another level of abstraction to separate out the abstract parts from the bits that actually start to condense the class into something concrete. The only thing you should want to do with an abstract class is to extend it - to turn it into something less vague (or more concrete if you prefer).

Of course, Java can seem a little contradictory at times. In fact, writing a constructor for an abstract class is perfectly valid:

abstract class Vehicle {

// You might have some common variables defined here

Vehicle() { }
}

At first this seems a little stupid. Why can I write a constructor, which is designed to allow you to instantiate an object, when I'm not allowed to instantiate the class? The compiler will even create a default constructor for you if you don't write one!

The answer there is that you are allowed to instantiate an abstract class - you're just not allowed to instantiate it directly using the new keyword. But the most important part of abstract classes is that they're designed to be extended.

When you instantiate a subclass of an abstract class, you either explicitly or implicitly call super(); inside the constructor:

public class Car extends Vehicle {
public Car() {
super(); // If you don't put this here, the compiler will!
}
}

This actually makes sense when you think about it - you can't have a Vehicle on it's own, but my car that's sat in the car park is definitely a Vehicle. Once I have a concrete extension to my concept of a Vehicle, Car in this case, then I can have a Vehicle.

Probably the most useful thing that this enables you to do is create generic collections. Because Vehicle is the superclass of all of the different types of Vehicle, I can say:

List<Vehicle> vehicles = new ArrayList<>();

Or if you prefer not to/can't use the diamond operator (<>):

List<Vehicle> vehicles = new ArrayList<Vehicle>();

This allows me to put any type of Vehicle into that collection:

vehicles.add(new Car());
vehicles.add(new Van());
vehicles.add(new Lorry());
vehicles.add(new Motorcycle());
// and so on...

Although there are many other advantages to this, too numerous to cover in this answer.

Instantiating an abstract class in Java

An abstract class is like a bike, without wheels. It has spaces defined for wheels, but the bike frame seller leaves the type of wheels to the final seller. It just points out where the wheels should attach to the frame and which bolts to be used. The bike has a chain, leading to where the back wheel should go, so that when the peddles are turned, the back wheel will be propelled forward.

Bike without wheels.

You can try riding that bike, but it won't move without wheels attached. An error will occur when the peddles are turned because there is no wheel to turn.

You need the concrete seller to define the wheels will operate, as long as they are attached in the pre-defined way.

square wheel bike
Image by https://www.flickr.com/photos/vrogy/, licensed CC-BY 2.0

So trying to ride the bike without wheels is you trying instantiate the abstract class.

Even if you get it working it's useless and will throw errors when you peddle forwards due to lacking wheels.

When you instantiate the square wheel bike, it will work properly, and move you forward when you peddle forwards.

The instantiation of the superclass is purely for the chain to be attached, the steeringhweel being able to move, the height of the saddle being set, all the standard features that do not include the wheels being set.
Wheels are not the abstract bike's concern. That's the concrete classes concern to set up.

Can we instantiate an abstract class directly?

You can't directly instantiate an abstract class, but you can create an anonymous class when there is no concrete class:

public class AbstractTest {
public static void main(final String... args) {
final Printer p = new Printer() {
void printSomethingOther() {
System.out.println("other");
}
@Override
public void print() {
super.print();
System.out.println("world");
printSomethingOther(); // works fine
}
};
p.print();
//p.printSomethingOther(); // does not work
}
}

abstract class Printer {
public void print() {
System.out.println("hello");
}
}

This works with interfaces, too.

How to instantiate an abstract class without using new and delete?

You need a pointer or reference to the object for polymorphism to work, but you can create that object in whatever way you want.

Concrete c;

c.method1(); // no polymorphism, using concrete directly
c.method2();

Interface* f = &c;

f->method1(); // polymorphism through Interface pointer
f->method2();

Interface& f2 = c;

f2.method1(); // polymorphism through reference
f2.method2();

Another way to avoid manual new and delete is to use a smart pointers.

#include <memory>

std::unique_ptr<Interface> upf = std::make_unique<Concrete>();

upf->method1();
upf->method2();

Can we instantiate an abstract class? Is it possible?

You can create a reference of an abstract class, but cant instantiate it. For eg.

public abstract class AbstractClass {

public abstract void abstractMethod();
public void concreteMethod(){
System.out.println("am in concreteMethod");
}

}

public class ExtndClass extends AbstractClass{

@Override
public void abstractMethod() {
// TODO Auto-generated method stub
System.out.println(" am in extended class");
}
public static void main(String...arg){
AbstractClass abs = new ExtndClass();
abs.abstractMethod();
abs.concreteMethod();

}

}

Output:

am in extended class
am in concreteMethod

How does this Java code instantiate an abstract class?

Adding the {} introduces the syntax for an anonymous inner class.

The anonymous class expression consists of the following:

  • The new operator

  • The name of an interface to implement or a class to extend. In this example, the anonymous class is implementing the interface HelloWorld.

  • Parentheses that contain the arguments to a constructor, just like a normal class instance creation expression. Note: When you implement an interface, there is no constructor, so you use an empty pair of parentheses, as in this example.

  • A body, which is a class declaration body. More specifically, in the body, method declarations are allowed but statements are not.

You are declaring an anonymous inner class that subclasses OurClass. The body of this class is empty: {}. This anonymous inner class is not abstract, so you are able to instantiate it.

When you remove the {}, the compiler thinks that you are directly instantiating OurClass, an abstract class, so it disallows it.



Related Topics



Leave a reply



Submit