Java Inheritance Fields

Java inheritance fields

First, see Hiding Fields (emphasis added)

Within a class, a field that has the same name as a field in the superclass hides the superclass's field, even if their types are different

In other words, this isn't "inheritance" since you're actually hiding A's i behind B's i, and you are using a reference object of A, so you are getting its fields. If you did B b = new B(), you would see 20, as expected.


If you expect true overrides, try using methods.

class A {
public int get() {
return 10;
}
}

class B extends A {
@Override
public int get() {
return 20;
}
}

See

A a = new B();
System.out.print(a.get()); // 20

If you really want to see both at once, see this example.

class A {
int i = 10;
}

class B extends A {
int i = 20;

@Override
public String toString() {
return String.format("super: %d; this: %d", super.i, this.i);
}
}

And

A a = new B();
System.out.print(a); // super: 10; this: 20

Do subclasses inherit private fields?

Most of the confusion in the question/answers here surrounds the definition of Inheritance.

Obviously, as @DigitalRoss explains an OBJECT of a subclass must contain its superclass's private fields. As he states, having no access to a private member doesn't mean its not there.

However. This is different than the notion of inheritance for a class. As is the case in the java world, where there is a question of semantics the arbiter is the Java Language Specification (currently 3rd edition).

As the JLS states (https://docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.2):

Members of a class that are declared
private are not inherited by
subclasses of that class. Only members
of a class that are declared protected
or public are inherited by subclasses
declared in a package other than the
one in which the class is declared.

This addresses the exact question posed by the interviewer: "do subCLASSES inherit private fields". (emphasis added by me)

The answer is No. They do not. OBJECTS of subclasses contain private fields of their superclasses. The subclass itself has NO NOTION of private fields of its superclass.

Is it semantics of a pedantic nature? Yes. Is it a useful interview question? Probably not. But the JLS establishes the definition for the Java world, and it does so (in this case) unambiguously.

EDITED (removed a parallel quote from Bjarne Stroustrup which due to the differences between java and c++ probably only add to the confusion. I'll let my answer rest on the JLS :)

Subclass inherited field is never used

You are asking the wrong question. There may or may not be a problem, but focusing on the data contained in the classes is wrong. You must focus on their behavior.

In her keynote address "Data Abstraction and Hierarchy" Barbara Liskov introduced what is commonly known as the Liskov Substitution Principle, expanded on in the paper "A Behavioral Notion of Subtyping" by Liskov and Jeannette Wing. The idea is that one type is a subtype of another if the subtype could replace the supertype everywhere in a program without impacting its correctness; that is, without breaking it.

What would happen if all Parent instances in your program were replaced with Child instances? Can the child do everything the parent does? Does it support the same operations? Will it produce the same results?

If the answer to that is yes, then Child is a subtype of Parent. If the answer to that is no, then it is not and it should not be a subclass of it. Whether field c is relevant depends entirely on how it is used.

Inheritance in Java (public or private for class fields?)

You should use protected instead of public. It will also serve ur purpose of inheritance and other class needs to use setter methods to modify fields.

How does inheritance of instance fields work in this particular code?

why does the output comes 5,5?

Because A.display() only knows about the fields A.a and A.b. Those are the only fields that any code in A knows about. It looks like you expect the declarations in B to "override" the existing field declarations. They don't. They declare new fields which hide the existing fields. Variables don't behave virtually in the way that methods do - the concept of overriding a variable simply doesn't exist. From the JLS section 8.3:

If the class declares a field with a certain name, then the declaration of that field is said to hide any and all accessible declarations of fields with the same name in superclasses, and superinterfaces of the class.

You can get the effect you want by changing B so that its constructor changes the values of the existing fields that it inherits from A instead:

class B extends A {
B() {
a = 5;
b = 6;
}
}

Note that these are not variable declarations. They're just assignments. Of course in most code (well, most code I've seen anyway) the fields in A would be private, so couldn't be accessed from B, but this is just example for the purpose of explaining the language behaviour.

Confused about inheriting methods and fields in Java

Because it goes up in hierarchy when a called method is not found in a Subclass object, the Subclass constructor calls super(); implicitly to make sure there's a Superclass object available to call inherited methods from.

The constructor (in the child and parent) will be invoked when you create the object itself and not when you invoke methods on an object (as you need a fully constructed object for invoking methods on it).

The reason why you don't see the printed class name as A is that the getClass() method returns the runtime type of the object (which is B)

From javadoc, (emphasis mine)

Returns the runtime class of this Object. The returned Class object is the object that is locked by static synchronized methods of the represented class.

Reference:

What is a "runtime class" in Java?

Hiding Fields in Java Inheritance

In java, fields are not polymorphic.

Father father = new Son();
System.out.println(father.i); //why 1? Ans : reference is of type father, so 1 (fields are not polymorphic)
System.out.println(father.getI()); //2 : overridden method called
System.out.println(father.j); //why 10? Ans : reference is of type father, so 2
System.out.println(father.getJ()); //why 10? there is not overridden getJ() method in Son class, so father.getJ() is called

System.out.println();

// same explaination as above for following
Son son = new Son();
System.out.println(son.i); //2
System.out.println(son.getI()); //2
System.out.println(son.j); //20
System.out.println(son.getJ()); //why 10?

Can inherited method access subclass fields in Java

Although a fair answer by @Makoto I feel the OP question's intend is not properly answered.

The question is about why the re-declared fishType in the Marlin class is not honored by the inherited getFishType() method when called on an Marlin instance.

This is even more curious when you think of how differently method lookup works (as opposed to field lookup): If you added e.g. a method Fish::getT():protected String getT() {return "Fish";} and overrode it in Marlin::getT() with protected String getT() {return "Marlin";} and called this new method in Fish::getFishType() instead of accessing the field, the call to marlin1.getFishType() would actually produce "Marlin". - Here, the subclass method is used in the inherited method, not the parent method of the same name. This is because method lookup always starts at the current instance.

I think the answer is indicated by the quote from the Java docs given by @Makoto: The re-declared field "hides" all other accessible declarations of the same name in the inheritance hierarchy (whereas a re-declared method "overrides" previous declarations of the same name and signature). I take this to mean that the Marlin.fishType has to be considered like a completely different symbol from Fish.fishType (with accidentally the same name). And Fish.getFishType() just sees its own version of it.



Related Topics



Leave a reply



Submit