I didn't know much about Java inheritance. I thought I knew it somehow, but I didn't understand it somehow, yes. : innocent:
In this article, I would like to introduce the Java inheritance that I personally experienced, "I knew" and "I didn't". I hope it helps you to understand Java inheritance.
※ Caution
coming soon
Inheritance is ** "creating (defining) a new class based on an existing class" **. This time, -Inheritance class: ** Super class ** or ** Base class ** -Inherited class: ** Subclass ** or ** Derived class ** (In this article, we use the expression superclass / subclass).
In the example below, we are creating a Cat class from the Mammals class.
//Super class
class Mammals { }
//Subclass
class Cat extends Mammals { }
That's all for inheritance. It's easy!
... I know that! However, I don't know what will happen with inheritance (especially me).
From the next chapter, four perspectives that I personally pay attention to
For example, a declaration like ↓ will result in a compilation error.
//Super class part 1
class Mammals { }
//Super class part 2
class Reptiles { }
//Subclass
class Cat extends Mammals, Reptiles { }
See the code below. The abstract class Mammals has abstract methods eact, walk, and concrete methods sleep. In the Cat class that inherits Mammals, the walk and sleep methods are overridden.
Mammals.java
public abstract class Mammals {
public abstract void eat();
public abstract void walk();
public void sleep() {}
}
Cat.java
public class Cat extends Mammals {
public void walk() {}
public void sleep() {}
}
By the way, it is the code of ↑, but when I compile it, I get an error (If you look at it with an editor such as Eclipse, VS Code, it is definitely red and red).
The reason is, as you might expect, ** we haven't overridden the abstract methods of the abstract class in the concrete class **. This time, I get a compile error because I haven't overloaded Mammal's eat () in Cat. Override all abstract methods [^ 20].
The code below inherits from the Mammals class to create the Cat and Dog classes.
class Mammals { } //Mammal class
class Cat extends Mammals { } //Cat class
class Dog extends Mammals { } //Dog class
public class Main {
public static void main(String[] args) {
Cat catA = new Cat();
Dog dogA = new Dog();
//Cast an instance of Cat type to Mammal type
Mammals mammals = (Mammals) catA; // OK
//Cast an instance of Cat type to Dog type
Dog dogB = (Dog) catA; //NG compilation error
}
}
Java also ** checks if it can be cast at compile time (= cast to a class that has an inheritance relationship) **. So it's a compile error, not a run-time error!
Code that cannot be cast in general, not just inheritance, will result in a compile error.
The following code will result in a compilation error. This is because when inheriting the Mammals class and overriding the eat method in the Cat class, the disclosure range is stricter than the original eat method.
class Mammals {
void eat() {}
}
class Cat extends Mammals {
private void eat() {}
}
The following are commonly used method accessors (access modifiers).
//Strict ← Disclosure range → Loose
private protected /*(No accessor)*/ public
Accessor | Description |
---|---|
private | Only available from within the same class |
protected | Available from classes in the same package or classes that inherit the target class |
(No accessor) | Only available from classes in the same package |
public | Available from any class |
Even if you inherit it, you cannot inherit it ** Private fields and methods (also constructors) ** is!
At the top, I said, "The constructor cannot be inherited even if it is inherited", but there is something to be aware of. That is, the ** superclass constructor is executed ** before the subclass constructor is executed.
See the code below. There are classes A, B, C, where C inherits B and B inherits A. And in each constructor, the class name is output to the console (the code is quoted from Reference 2 in some different formats).
A.java
class A {
public A() {
System.out.print("A");
}
}
class B extends A {
public B() {
System.out.print("B");
}
}
class C extends B {
public C() {
System.out.print("C");
}
}
public class Main {
public static void main(String[] args) {
new C(); // ABC
}
}
And did you see what happens when you run this main () ... Yes, ** A, B, C constructors are all running! !! ** **
... I'm sorry, I exaggerated [^ 30].
The whole thing is an explanation of why this happens, but I would like to quote from Reference 3 p.429.
Actually, in Java, the rule is that" all constructors must call the constructor of the inner instance part (= parent class) at the beginning. "
[^ 35]
In other words, considering the true appearance and execution order of the previous code,
A.java
class A {
public A() {
System.out.print("A"); // 3
}
}
class B extends A {
public B() {
super(); //Call A's constructor 2
System.out.print("B"); // 4
}
}
class C extends B {
public C() {
super(); //Call B's constructor 1
System.out.print("C"); // 5
}
}
public class Main {
public static void main(String[] args) {
new C(); //Instantiate C 0
}
}
If B () is executed when C () is called, A () is called inside B (), and so on, if the inheriting class inherits another class, Attempts to execute the constructor of the inherited class first.
Also, inside a subclass, if you haven't called the superclass class constructor, the compiler will automatically add super ()
[^ 37] [^ 40]!
However,
-Explicitly call the superclass constructor (super ()
, super (str)
, etc.)
-Call the overloaded constructor (this ()
or this (str)
)
If you're doing either, the compiler won't add super ()
on its own.
The constructor of the subclass calls the constructor of the superclass ... Even if you know that, if you call the constructor of a class that is inherited many times like this, you will be disappointed.
In connection with "02. Pay attention to the execution order of constructors", such a trigger also appears. that is, ** Code that double-calls the superclass constructor will result in a compile error ** about it.
First, take a look at the following code! (Reference 2 p.362-363, quoted with some changes in format)
Mammal class
public class Mammals {
String name;
int age;
public Mammals(String name, int age) {
this.name = name;
this.age = age;
}
}
Cat class
class Cat extends Mammals {
String color
publip Cat(String color) {
this.color = color;
}
public Cat(String name, int num, String color) {
super(name, num);
this(color);
}
}
Main class
public class Main {
public static void main(String[] args) {
Cat cat1 = new Cat("white");
Cat cat2 = new Cat("mike", 2, "Black");
System.out.println(cat1.name + ", " + "" + "")
}
}
Now, what do you think of this code, compiler?
The correct answer is a compile error on lines 3 and 8 of the cat class
!
To see why, we'll assume that this code has been executed and follow the process for each instance created!
① Process to generate cat1
instance
Since there is one argument like Cat cat1 = new Cat ("white ");
, publip Cat (String color)
is executed.
Before ..., Cat inherits from Mammals, so the constructor for Mammals is executed.
String color
publip Cat(String color) {
super(); //Automatically added at compile time
this.color = color;
}
However, the Mammals class does not have a no-argument constructor public Mammals ();
!
I get an error on the line that says publip Cat (String color)
when I try to execute a method that doesn't exist [^ 45].
(2) Processing to generate a cat2
instance
This time, we are creating an instance with three arguments.
Therefore, what is executed is the corresponding constructor below!
public Cat(String name, int num, String color) {
super(name, num);
this(color);
}
First, the superclass constructor publip Cat (String color)
is executed. This is not a problem as it exists.
But the code on the next line, this time running the Cat class constructor publip Cat (String color)
.
I think that the same error as in ① will occur, but I get caught in another kind of compilation error.
The reason is that you will ** call the superclass constructor twice **.
In Java, it is not possible to call an overloaded constructor after calling the superclass constructor.
[^ 50]
This time, publip Cat (String color)
is the overloaded constructor. This was done after super ();
, so I get an error.
In the actual test, inside the constructor,
super();
this();
When I look at the code, I get a compile error at the this ();
part! It seems good to remember!
Thank you for reading to the end.
[ref]: List of references [^ 5]: Editors and compilers usually tell you, so it doesn't matter if you don't know it, but if you have to notice it on your own, you can't say that! It means. [^ 20]: As an aside, abstract methods can only be defined in abstract classes. If you don't implement the method in the Cat class, it's a good idea to attach the Cat class as well. [^ 30]: I wrote it exaggeratedly. [^ 35]: Reference 3 From p.429 [^ 37]: It's not like the code appears on its own. The code is only compiled with the body written in super (). [^ 40]: In the first place, it is an interpretation of whether you have to execute the constructor of the superclass, but if the constructor is a method to generate the class, it will be the base before creating the subclass. Is it a place where you have to prepare from the class you are in (= super class)? [^ 45]: The Java compiler also checks if the method you are trying to execute exists, so it is treated as a compilation error! [^ 50]: Reference 2 From p.416
Recommended Posts