Extending abstract classes java

Abstract Class in Java with example

A class that is declared using “abstract” keyword is known as abstract class. It can have abstract methods(methods without body) as well as concrete methods (regular methods with body). A normal class(non-abstract class) cannot have abstract methods. In this guide we will learn what is a abstract class, why we use it and what are the rules that we must remember while working with it in Java.

An abstract class can not be instantiated, which means you are not allowed to create an object of it. Why? We will discuss that later in this guide.

Why we need an abstract class?

Lets say we have a class Animal that has a method sound() and the subclasses(see inheritance) of it like Dog , Lion , Horse , Cat etc. Since the animal sound differs from one animal to another, there is no point to implement this method in parent class. This is because every child class must override this method to give its own implementation details, like Lion class will say “Roar” in this method and Dog class will say “Woof”.

Читайте также:  Python find lines that start with

So when we know that all the animal child classes will and should override this method, then there is no point to implement this method in parent class. Thus, making this method abstract would be the good choice as by making this method abstract we force all the sub classes to implement this method( otherwise you will get compilation error), also we need not to give any implementation to this method in parent class.

Since the Animal class has an abstract method, you must need to declare this class abstract.

Now each animal must have a sound, by making this method abstract we made it compulsory to the child class to give implementation details to this method. This way we ensures that every animal has a sound.

Abstract class Example

//abstract parent class abstract class Animal < //abstract method public abstract void sound(); >//Dog class extends Animal class public class Dog extends Animal < public void sound()< System.out.println("Woof"); >public static void main(String args[]) < Animal obj = new Dog(); obj.sound(); >>

Hence for such kind of scenarios we generally declare the class as abstract and later concrete classes extend these classes and override the methods accordingly and can have their own methods as well.

Abstract class declaration

An abstract class outlines the methods but not necessarily implements all the methods.

//Declaration using abstract keyword abstract class A < //This is abstract method abstract void myMethod(); //This is concrete method with body void anotherMethod()< //Does something >>

Rules

Note 1: As we seen in the above example, there are cases when it is difficult or often unnecessary to implement all the methods in parent class. In these cases, we can declare the parent class as abstract, which makes it a special class which is not complete on its own.

A class derived from the abstract class must implement all those methods that are declared as abstract in the parent class.

Note 2: Abstract class cannot be instantiated which means you cannot create the object of it. To use this class, you need to create another class that extends this this class and provides the implementation of abstract methods, then you can use the object of that child class to call non-abstract methods of parent class as well as implemented methods(those that were abstract in parent but implemented in child class).

Note 3: If a child does not implement all the abstract methods of abstract parent class, then the child class must need to be declared abstract as well.

Do you know? Since abstract class allows concrete methods as well, it does not provide 100% abstraction. You can say that it provides partial abstraction. Abstraction is a process where you show only “relevant” data and “hide” unnecessary details of an object from the user.

Interfaces on the other hand are used for 100% abstraction (See more about abstraction here).
You may also want to read this: Difference between abstract class and Interface in Java

Why can’t we create the object of an abstract class?

Because these classes are incomplete, they have abstract methods that have no body so if java allows you to create object of this class then if someone calls the abstract method using that object then What would happen?There would be no actual implementation of the method to invoke.
Also because an object is concrete. An abstract class is like a template, so you have to extend it and build on it before you can use it.

Example to demonstrate that object creation of abstract class is not allowed

As discussed above, we cannot instantiate an abstract class. This program throws a compilation error.

abstract class AbstractDemo < public void myMethod()< System.out.println("Hello"); >abstract public void anotherMethod(); > public class Demo extends AbstractDemo < public void anotherMethod() < System.out.print("Abstract method"); >public static void main(String args[]) < //error: You can't create object of it AbstractDemo obj = new AbstractDemo(); obj.anotherMethod(); >>
Unresolved compilation problem: Cannot instantiate the type AbstractDemo

Note: The class that extends the abstract class, have to implement all the abstract methods of it, else you have to declare that class abstract as well.

Abstract class vs Concrete class

A class which is not abstract is referred as Concrete class. In the above example that we have seen in the beginning of this guide, Animal is a abstract class and Cat , Dog & Lion are concrete classes.

  1. An abstract class has no use until unless it is extended by some other class.
  2. If you declare an abstract method in a class then you must declare the class abstract as well. you can’t have abstract method in a concrete class. It’s vice versa is not always true: If a class is not having any abstract method then also it can be marked as abstract.
  3. It can have non-abstract method (concrete) as well.

I have covered the rules and examples of abstract methods in a separate tutorial, You can find the guide here: Abstract method in Java
For now lets just see some basics and example of abstract method.
1) Abstract method has no body.
2) Always end the declaration with a semicolon(;).
3) It must be overridden. An abstract class must be extended and in a same way abstract method must be overridden.
4) A class has to be declared abstract to have abstract methods.

Note: The class which is extending abstract class must override all the abstract methods.

Example of Abstract class and method

abstract class MyClass < public void disp()< System.out.println("Concrete method of parent class"); >abstract public void disp2(); > class Demo extends MyClass < /* Must Override this method while extending * MyClas */ public void disp2() < System.out.println("overriding abstract method"); >public static void main(String args[]) < Demo obj = new Demo(); obj.disp2(); >>
overriding abstract method

Источник

Extending abstract classes with abstract classes in Java

When I was creating the Java::Geci abstract class AbstractFieldsGenerator and AbstractFilteredFieldsGenerator I faced a not too complex design issue. I would like to emphasize that this issue and the design may seem obvious for some of you, but during my recent conversation with a junior developer (my son, Mihály specifically, who also reviews my articles because his English is way better than mine) I realized that this topic may still be of value. Anyway. I had these two classes, fields and filtered fields generator. The second class extends the first one

adding extra functionality and the same time it should provide the same signature for concrete implementation. What does it mean? These generators help to generate code for a specific class using reflection. Therefore the input information they work on is a Class object. The fields generator class has an abstract method process() , which is invoked for every field. It is invoked from an implemented method that loops over the fields and does the invocation separately for each. When a concrete class extends AbstractFieldsGenerator and thus implements this abstract method then it will be called. When the same concrete class is changed so that it extends AbstractFilteredFieldsGenerator then the concrete method will be invoked only for the filtered method. I wanted a design so that the ONLY change that was needed in the concrete class is to change the name.

abstract classes

Abstract class problem definition

  • F overrides m() making it concrete implementing the extra functionality in m() and calls a new abstract method, say mx()
  • F overrides the method p() with a version that provides the extra functionality (filtering in the example above) and calls the still abstract method m()

The first approach does not fulfill the requirement that the signature to be implemented by the concrete class C should remain the same. The second approach throws the already implemented functionality of A to the garbage and reimplements it a bit different way. In practice this is possible, but it definitely is going to be some copy/paste programming. This is problematic, let me not explain why.

The root of the problem

In engineering when we face a problem like that, it usually means that the problem or the structure is not well described and the solution is somewhere in a totally different area. In other words, there are some assumptions driving our way of thinking that are false. In this case, the problem is that we assume that the abstract classes provide ONE extension “API” to extend them. Note that the API is not only something that you can invoke. In the case of an abstract class, the API is what you implement when you extend the abstract class. Just as libraries may provide different APIs for different ways to be used (Java 9 HTTP client can send() and also sendAsync() ) abstract (and for the matter of fact also non-abstract) classes can also provide different ways to be extended for different purposes.

There is no way to code F reaching our design goal without modifying A . We need a version of A that provides different API to create a concrete implementation and another, not necessarily disjunct/orthogonal one to create a still abstract extension.

The difference between the APIs in this case is that the concrete implementation aims to be at the end of a call-chain while the abstract extension wants to hook on the last but one element of the chain. The implementation of A has to provide API to be hooked on the last but one element of the call-chain. This is already the solution.

Solution

We implement the method ma() in the class F and we want p() to call our ma() instead of directly calling m() . Modifying A we can do that. We define ma() in A and we call ma() from p() . The version of ma() implemented in A should call m() without further ado to provide the original “API” for concrete implementations of A . The implementation of ma() in F contains the extra functionality (filtering in the example) and then it calls m() . That way any concrete class can extend either A or F and can implement m() with exactly the same signature. We also avoided copy/paste coding with the exception that calling m() is a code that is the same in the two versions of ma() .

If we want the class F extendable with more abstract classes then the F::ma implementation should not directly call m() but rather a new mf() that calls m() . That way a new abstract class can override mf() giving again new functionality and invoke the abstract m() .

Takeaway

  1. Programming abstract classes is complex and sometimes it is difficult to have a clear overview of who is calling who and which implementation. You can overcome this challenge if you realize that it may be a complex matter. Document, visualize, discuss whatever way may help you.
  2. When you cannot solve a problem (in the example, how to code F ) you should challenge the environment (the class A we implicitly assumed to be unchangeable by the wording of the question: “How to implement F ?”).
  3. Avoid copy/paste programming. (Pasta contains a lot of CH and makes your code fat, the arteries get clogged and finally, the heart of your application will stop beating.)
  4. Although not detailed in this article, be aware that the deeper the hierarchy of abstraction is the more difficult it is to have a clear overview of who calls whom (see also point number 1).
  • Find a sample demo application at https://github.com/verhas/abstractchain
  • Find the original, a tad more complex application that has this pattern at https://github.com/verhas/javageci

Published on Java Code Geeks with permission by Peter Verhas, partner at our JCG program. See the original article here: Extending abstract classes with abstract classes in Java

Источник

Оцените статью