I know the meaning and definition of abstract classes, but when to use them and what good things are there? Let's compare the program implemented with the abstract class and the program implemented without it to confirm the same requirement.
Suppose that the types of printers are inkjet and laser. Create a program that manages multiple of them and displays a list of managed printer information.
https://paiza.io/projects/Iwnh9NgDAaxPSZC36uZqsw
Class structure:
There are only InkjetPrinter and LaserPrinter classes. Each has a model name (mModelName) and the remaining number of sheets (mPaper) as member variables. It also has a getPrinterInfo () function that returns printer information.
The difference is that the InkjetPrinter has the ink level (mRemainingInk) and the LaserPrinter has the toner level (mRemainingToner).
https://paiza.io/projects/Xs-iNK2-SYDnlYIp1oWF3w
Class structure:
We have created an abstract class AbstractPrinter by generalizing the common parts of the InkjetPrinter class and LaserPrinter class (member variable model name, remaining amount of paper, and function that returns printer information). The InkjetPrinter and LaserPrinter classes inherit from AbstractPrinter.
Both output the same result.
Output result
[Inkjet]Epson P1 Number of printable sheets: 10
[Inkjet]Canon C1 Number of printable sheets: 20
[laser]Xerox X1 Number of printable sheets: 100
[laser]Ricoh R1 Number of printable sheets: 50
[laser]Richo R2 Number of printable sheets: 200
I can give you two points.
First of all, class structure. An independent class and an abstracted class. The concept of abstract classes is explained in detail in books and sites that explain object orientation, so I will omit it here.
The other point is how to use it from the management side. Let's take a closer look at this.
Main when not using abstract class()
public static void main(String[] args) throws Exception {
//Register the inkjet printer to be managed.
InkjetPrinter[] inkjets = {
new InkjetPrinter("Epson P1", 10),
new InkjetPrinter("Canon C1", 20),
};
//Register the laser printer to be managed.
LaserPrinter[] lasers = {
new LaserPrinter("Xerox X1", 100),
new LaserPrinter("Richo R1", 50),
new LaserPrinter("Richo R2", 200),
};
//List the managed printers.
//First, an inkjet printer.
for(int i = 0; i < inkjets.length; i++ ){
System.out.println(inkjets[i].getPrinterInfo());
}
//Next, a laser printer.
for(int i = 0; i < lasers.length; i++ ){
System.out.println(lasers[i].getPrinterInfo());
}
}
There is no relationship between the InkjetPrinter class and the LaserPrinter class, and they are independent "types".
** Objects of the InkjetPrinter class can only be stored in variables of type InkjetPrinter, and objects of the LaserPrinter class can only be stored in variables of type LaserPrinter. ** **
Therefore, a variable of the type for each printer type (in this case, an array) is prepared, the printer object is stored, and the printer list is output by looping each.
Main when using abstract class()
public static void main(String[] args) throws Exception {
//Register the printer to be managed.
AbstractPrinter[] printers = {
new InkjetPrinter("Epson P1", 10),
new InkjetPrinter("Canon C1", 20),
new LaserPrinter("Xerox X1", 100),
new LaserPrinter("Richo R1", 50),
new LaserPrinter("Richo R2", 200),
};
//List the managed printers.
for(int i = 0; i < printers.length; i++ ){
System.out.println(printers[i].getPrinterInfo());
}
}
The InkjetPrinter class and LaserPrinter class are derived from the class "AbstractPrinter" which is an abstraction of "printer". The AbstractPrinter class is the common parent class.
** Variables can store objects of that type and objects derived from that type. ** **
Therefore, the AbstractPrinter type variable can store the InkjetPrinter class object and the LaserPrinter class object, and the objects contained in this variable can be treated as the AbstractPrinter class.
As a result, the variables that manage the printer are unified, and the processing for displaying is also unified.
By introducing an abstract class, the variables to be managed and the display process have become smarter. This alone is good, but there are some very good things such as enhancements that make you "resistant to changes".
Let's say you have a remodeling requirement to add a dot impact printer to your printer type.
If you don't use an abstract class, the source is: This is the line added by the process that commented "★ Add ★".
Class structure:
Main when not using abstract class()
public static void main(String[] args) throws Exception {
//Register the inkjet printer to be managed.
InkjetPrinter[] inkjets = {
new InkjetPrinter("Epson P1", 10),
new InkjetPrinter("Canon C1", 20),
};
//Register the laser printer to be managed.
LaserPrinter[] lasers = {
new LaserPrinter("Xerox X1", 100),
new LaserPrinter("Richo R1", 50),
new LaserPrinter("Richo R2", 200),
};
//★ Addition ★
//Register the dot impact printer to be managed.
DotimpactPrinter[] dotimpacts = {
new DotimpactPrinter("NEC N1", 100),
new DotimpactPrinter("Oki O1", 50),
};
//List the managed printers.
//First, an inkjet printer.
for(int i = 0; i < inkjets.length; i++ ){
System.out.println(inkjets[i].getPrinterInfo());
}
//Next, a laser printer.
for(int i = 0; i < lasers.length; i++ ){
System.out.println(lasers[i].getPrinterInfo());
}
//★ Addition ★
//Next is the dot impact printer.
for(int i = 0; i < dotimpacts.length; i++ ){
System.out.println(dotimpacts[i].getPrinterInfo());
}
}
Class structure:
Main when using abstract class()
public static void main(String[] args) throws Exception {
//Register the printer to be managed.
AbstractPrinter[] printers = {
new InkjetPrinter("Epson P1", 10),
new InkjetPrinter("Canon C1", 20),
new LaserPrinter("Xerox X1", 100),
new LaserPrinter("Richo R1", 50),
new LaserPrinter("Richo R2", 200),
new DotimpactPrinter("NEC N1", 100), //★ Addition ★
new DotimpactPrinter("Oki O1", 50), //★ Addition ★
};
//List the managed printers.
for(int i = 0; i < printers.length; i++ ){
System.out.println(printers[i].getPrinterInfo());
}
}
For those who do not use abstract classes, we have added variables that manage the dot impact printer and loop processing that displays them. Similar processing has increased. It's redundant.
On the other hand, those who used the abstract class only added the dot impact printer object to the printers variable that manages the printer, and there was no change in the display process. The amount of program modification is small.
In fact, this advantage is not so much the effect of abstract classes as it is the generalization and inheritance of classes. Using an abstract class means abstracting + generalizing / inheriting, so you can benefit from generalization / inheritance.
Recommended Posts