'What is the point of using abstract methods?
What's the point of using "abstract methods"? An abstract class cannot be instantiated, but what about the abstract methods? Are they just here to say "you have to implement me", and if we forget them, the compiler throws an error?
Does it mean something else? I also read something about "we don't have to rewrite the same code", but in the abstract class, we only "declare" the abstract method, so we will have to rewrite the code in the child class.
Can you help me understand it a bit more? I checked the other topics about "abstract class/methods" but I didn't find an answer.
Solution 1:[1]
Besides the reminder that you have to implement it, the big advantage is that anyone who references the object by its abstract class type (including this
in the abstract class itself) can use the method.
For instance, let's say we have a class responsible for taking state and manipulating it in some way. The abstract class is going to be responsible for getting the input, converting it to a long
(for instance) and combining that value with the previous value in some way -- that "some way" is the abstract method. The abstract class may look something like:
public abstract class StateAccumulator {
protected abstract long accumulate(long oldState, long newState);
public handleInput(SomeInputObject input) {
long inputLong = input.getLong();
state = accumulate(state, inputLong);
}
private long state = SOME_INITIAL_STATE;
}
Now you can define an addition accumulator:
public class AdditionAccumulator extends StateAccumulator {
@Override
protected long accumulate(long oldState, long newState) {
return oldState + newState;
}
}
Without that abstract method, the base class would have no way to say "handle this state somehow." We don't want to provide a default implementation in the base class, though, because it wouldn't mean much -- how do you define a default implementation for "someone else will implement this"?
Note that there's more than one way to skin a cat. The strategy pattern would involve declaring an interface that declares the accumulate
pattern, and passing an instance of that interface to the no-longer-abstract base class. In lingo terms, that's using composition instead of inheritance (you've composed an addition aggregator out of two objects, an aggregator and an adder).
Solution 2:[2]
Say you have three printers that you need to write drivers for, Lexmark
, Canon
, and HP
.
All three printers will have the print()
and getSystemResource()
methods.
However, print()
will be different for each printer, and getSystemResource()
remains the same for all three printers. You also have another concern, you would like to apply polymorphism.
Since getSystemResource()
is the same for all three printers, you can push this up to the super class to be implemented, and let the subclasses implement print()
. In Java, this is done by making print()
abstract in the super class. Note: when making a method abstract in a class, the class itself needs to be abstract as well.
public abstract class Printer{
public void getSystemResource(){
// real implementation of getting system resources
}
public abstract void print();
}
public class Canon extends Printer{
public void print(){
// here you will provide the implementation of print pertaining to Canon
}
}
public class HP extends Printer{
public void print(){
// here you will provide the implementation of print pertaining to HP
}
}
public class Lexmark extends Printer{
public void print(){
// here you will provide the implementation of print pertaining to Lexmark
}
}
Notice that HP, Canon and Lexmark classes do not provide the implementation of getSystemResource()
.
Finally, in your main class, you can do the following:
public static void main(String args[]){
Printer printer = new HP();
printer.getSystemResource();
printer.print();
}
Solution 3:[3]
Abstract classes are classes that contain one or more abstract methods. An abstract method is a method that is declared, but contains no implementation. Abstract classes may not be instantiated, and require subclasses to provide implementations for the abstract methods. Let's look at an example of an abstract class, and an abstract method.
Suppose we were modeling the behavior of animals, by creating a class hierachy that started with a base class called Animal. Animals are capable of doing different things like flying, digging and walking, but there are some common operations as well like eating and sleeping and making noise. Some common operations are performed by all animals, but in a different way as well. When an operation is performed in a different way, it is a good candidate for an abstract method (forcing subclasses to provide a custom implementation). Let's look at a very primitive Animal base class, which defines an abstract method for making a sound (such as a dog barking, a cow mooing, or a pig oinking).
public abstract Animal {
public void sleep{
// sleeping time
}
public void eat(food)
{
//eat something
}
public abstract void makeNoise();
}
public Dog extends Animal {
public void makeNoise() {
System.out.println("Bark! Bark!");
}
}
public Cow extends Animal {
public void makeNoise() {
System.out.println("Moo! Moo!");
}
}
Note that the abstract keyword is used to denote both an abstract method, and an abstract class. Now, any animal that wants to be instantiated (like a dog or cow) must implement the makeNoise method - otherwise it is impossible to create an instance of that class. Let's look at a Dog and Cow subclass that extends the Animal class.
Now you may be wondering why not declare an abstract class as an interface, and have the Dog and Cow implement the interface. Sure you could - but you'd also need to implement the eat and sleep methods. By using abstract classes, you can inherit the implementation of other (non-abstract) methods. You can't do that with interfaces - an interface cannot provide any method implementations.
In simple word an interface should contain all abstract method but no implementation of method or we can’t define non abstract method in interface, in interface all the method should be abstract but in abstract class we can define both abstract and non abstract method, so for defining non abstract method we don’t have to define another class to implement the behavior of same object this is the advantage of abstract class over interface.
Solution 4:[4]
The abstract methods merely define a contract that derived classes must implement. It's is the way how you ensure that they actually always will.
So let's take for example an abstract class Shape
. It would have an abstract method draw()
that should draw it. (Shape
is abstract, because we do not know how to draw a general shape) By having abstract method draw
in Shape
we guarantee that all derived classed, that actually can be drawn, for example Circle
do implement draw
. Later if we forget to implement draw
in some class, that is derived from Shape
, compiler will actually help as giving an error.
Solution 5:[5]
Simply speaking, declaring a class to be "abstract", you are enforcing a "contract" for the child classes which inherit it, so it provides a good way to maintain the "contract".
Solution 6:[6]
If all an abstract does is declare abstract methods, you are correct, it's a bit silly, and an interface would likely be superior.
But often an abstract class implements some (maybe even all) of the methods, leaving only a few as abstract. For example, AbstractTableModel. This saves rewriting a lot of code.
Another "advantage" over an interface is that an abstract class can declare fields for subclasses to use. So, if you are pretty sure that any reasonable implementation would have a String named uniqueID, you could declare it, plus relevant getters/setters, in the abstract class, saving some typing later.
Solution 7:[7]
Abstract methods must be overriden by any subclass that will not be abstract.
So, for example you define an abstract class Log and you force the subclasses to override that method:
public abstract class Log{
public void logError(String msg){
this.log(msg,1)
}
public void logSuccess(String msg){
this.log(msg,2)
}
public abstract void log(String msg,int level){}
}
public class ConsoleLog{
public void log(String msg,int level){
if(level=1){
System.err.println(msg)
}else{
System.out.println(msg)
}
}
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 | Joseph M Cutcher III |
Solution 3 | Vincent J. Michuki |
Solution 4 | |
Solution 5 | spiralmoon |
Solution 6 | user949300 |
Solution 7 | santiagobasulto |