A
A
Alexander Popov2018-01-27 22:44:20
Java
Alexander Popov, 2018-01-27 22:44:20

Why is inheritance implemented this way in Java?

Good day to all,
I recently wrote a project in Java. At the same time, the behavior of the methods of the parent classes was somewhat surprising.
Quote from Wiki:

Virtual method (virtual function) - in object-oriented programming, a method (function) of a class that can be overridden in descendant classes so that the specific implementation of the method to be called will be determined at runtime. Thus, the programmer does not need to know the exact type of an object in order to work with it through virtual methods: it is enough to know that the object belongs to the class or descendant of the class in which the method is declared. One of the translations of the word virtual from English can be "actual", which is more appropriate in meaning.
Virtual methods are one of the most important techniques for implementing polymorphism. They allow you to create common code that can work both with objects of the base class and with objects of any of its descendant classes. In this case, the base class defines a way to work with objects, and any of its heirs can provide a concrete implementation of this way.

Now a specific case.
There is a class A with a type field of type String, there is a class B that inherits A.
It is assumed that A and all its descendant classes must have a getType () method that displays a type string (in general, the functionality is the same, and you don’t even need to redefine it ).
What we have as a result:
1. An attempt to do so
public class A {
    ...

    public String getType() {
        return this.type;
    }
    private String type = "null";
}

public class B {
    ...
    private String type = "type_B";
}

causes it to always print null. In general, one could assume such a development of events, since the field is private, and such a field is not available to objects of descendant classes. Although formally such fields seem to be inherited (?). In any case, the IDE writes that "field has private access in class A", and not "field does not exist".
2. An attempt to make a field protected in A and B, leaving everything else as it is, leads to a warning in the IDE that the field hides the parent class field, but the result of execution does not change at all.
3. Working ways (two pieces):
- Completely copy the implementation of the getType() method in B by adding the Override annotation. Not bad, it even allows you to leave both fields private. But this is a duplication of exactly the same code, moreover, it is simply elementary that you can forget to do it by inattention.
- Create a constructor in B that assigns a value to the type field, remove the declaration of the type field from B, and make it protected in A. It works, it looks good, except perhaps - in my case, for this I had to make a constructor where it was not needed, since the classes are very simple.
Question:
Why does the parent implementation work with the fields of the ancestor class? In the case of a private field, this is still relatively clear, but in the case of a protected field, it is not. After all, even at the time of the call, the object was in a variable of type B. At the same time, an implementation from A is called, this is normal if I did not redefine it in B, but the problem is that the field values ​​are taken from A! Why is it so implemented? In JS, for example, with its prototype chain, the result would be very different.
PS You can use Reflections in the implementation code of the method from A, in principle, to get the actual value of the object's field, but this is already completely perverted.
PPS The variant with a constructor is also bad because even if B has its own constructor, you can forget to assign values ​​to the required fields there, again due to inattention. It is more intuitive for the programmer to declare class fields along with their default values ​​at the bottom, in a single block. Sometimes it's even the first thing done when a derived class is created. Until the moment the constructor is written, you can simply forget about it, and no one will remind us that, it turns out, critical protected fields are not reassigned in our country :)

Answer the question

In order to leave comments, you need to log in

1 answer(s)
A
Alexander Movchan, 2018-01-27
@popov654

You cannot override field values, as it works with methods. In your example, you simply defined a new field with the same name, resulting in something called name shadowing .
If you are trying to implement reflection, it is better to use standard tools.
If you want to set the value of the parent field in the child , make a constructor in the parent with the appropriate parameter.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question