Session 6 |
Abstract classes
An abstract class is a class that is declared abstract
. Abstract classes cannot be instantiated (we cannot create instances of an abstract class), but they can be subclassed. The purpose of abstract classes is to be a parent to several related classes. In general, we use abstract classes when the object they represent is not a clear. In such cases, it is not possible to create instances of it.
An example of abstract classes importance can be seen in cases when we have a broad concept (like Automobile) but actual objects must be specific types (like electric car, diesel car and petrol car).
Abstract classes may or may not include abstract
methods (one is for sure: if a class includes abstract
methods, then the class itself must be declared abstract
).
An abstract method is a method that is declared without an implementation (it has no statements). It declares a modifier, return type, and method signature followed by a semicolon. Note: it is not possible to make an abstract
constructor or an abstract static
method!
An abstract
class and abstract
methods are defined like this:
public abstract class ClassName { modifier dataType instanceFieldName; // define abstract instance field, but do not instantiate modifier abstract returnType abstractMethodName(listOfParameters); // define abstract return type methods modifier abstract void abstractMethodName(listOfParameters); // define abstract void methods // declare non-abstract methods }
An abstract class is defined by the statement public abstract class ClassName
, whereas an abstract
method is defined by public abstract returnType methodName(listOfParameters);
.
When an abstract
class is subclassed, the subclass usually provides implementations for all of the abstract
methods in its parent class. However, if it does not, then the subclass must also be declared abstract
.
Let's consider an example.
public abstract class Dog { private String name; public Dog(String name) { this.name = name; } public abstract void barking(); }
Different cultures "hear" the dog's barks differently (more about barks can be found in Wiki: https://en.wikipedia.org/wiki/Bark_(sound) ):
public class EstonianDog extends Dog { public EstonianDog(String name) { super(name); } @Override public void barking() { System.out.println("Auh-auh!"); } }
public class RussianDog extends Dog { public RussianDog(String name) { super(name); } @Override public void barking() { System.out.println("Gav-gav!"); } }
public class KoreanDog extends Dog { public KoreanDog(String name) { super(name); } @Override public void barking() { System.out.println("Meong-meong!"); } }
Using polymorphism, it is possible to use the abstract class name as a variable data type. As a result we can create an array of the abstract class data type, but the elements of the array would be of the subclass data type:
public class TestDogs { public static void main(String[] args) { Dog d1 = new RussianDog("Šarik"); Dog d2 = new KoreanDog(""); Dog d3 = new EstonianDog("Muri"); Dog[] dogs = {d1, d2, d3}; for (Dog d : dogs){ d.barking(); } } }
import java.io.File; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; import java.nio.file.Files; class Person { private String firstName; private String lastName; Person(String firstName, String lastName) { this.firstName = firstName; this.lastName = lastName; } } abstract class GetPersonFromFile { protected abstract Person lineIntoPerson(String line); public List<Person> readPerson(File input) throws Exception { // Files.readAllLines reads from the file all lines into a list List<String> text = Files.readAllLines(input.toPath(), StandardCharsets.UTF_8); List<Person> people = new ArrayList<>(); for (String line : text) { people.add(lineIntoPerson(line)); } return people; } } class FirstAndLastName extends GetPersonFromFile { protected Person lineIntoPerson(String line) { String[] partOfName = line.split(" "); // Malle Mallikas return new Person(partOfName[0], partOfName[1]); } } class LastAndFirstName extends GetPersonFromFile { protected Person lineIntoPerson(String line) { String[] partOfName = line.split(", "); // Mallikas, Malle return new Person(partOfName[1], partOfName[0]); } } class TestEmployee { public static void main(String[] args) throws Exception { FirstAndLastName flname = new FirstAndLastName(); List<Person> nimed = flname.readPerson(new File("names.txt")); GetPersonFromFile secondReader = new LastAndFirstName(); List<Person> officialNames = secondReader.readPerson(new File("officialnames.txt")); // GetPersonFromFile reader = new GetPersonFromFile(); // error! } }
Even if we cannot create an instance of GetPersonFromFile
class, we can use its methods.
Connection to a website
Another example of abstract classes is java.net.URLConnection
via which it is possible to send or receive the data from the website. The only abstract method in this class is connect
which determines how to open the connection. The method is implemented in several subclasses like HttpURLConnection
, HttpsURLConnection
, FtpURLConnection
etc.
Useful link: Check API and have a look at methods of URLConnection abstract class.
Why do we need abstract classes?
Abstract classes are used to organize programs. The same program could be organized in many ways. Our example program could be written without an abstract class. But a real-world application might have hundreds of classes. Grouping classes together is important in keeping a program organized and understandable.
Remember:
- When we define abstract classes or abstract methods, we use the keyword
abstract
. - If a class is declared abstract, it cannot be instantiated.
- An abstract class does not produce instances, but instances of their subclasses can be created.
- Access modifiers such as public can be placed before abstract (not compulsory).
- An abstract class can contain both normal and abstract methods, the first containing the method body, the second having only the method definition.
- The implementation of the abstract methods is left to the inheriting class.
- If a class has at least one abstract method, then the class must be declared abstract.
- To use an abstract class, inherit it from another class (
extends
keyword), provide implementations to all the abstract methods in it.
Session 6 |