Child class private member called from Parent class public member - java

What is happening in the code below? Please explain the output:
class Parent{
private void fun(){
System.out.println("parent fun\n");
}
public void accessFun(){
System.out.println(this);
this.fun();
}
}
class Child extends Parent{
private void fun(){
System.out.println("child fun");
}
}
class Test{
public static void main(String[] args) {
Child a = new Child();
Parent b = new Parent();
Parent c = new Child();
a.accessFun();
b.accessFun();
c.accessFun();
}
}
Output:
Child#7960847b
parent fun
Parent#3b192d32
parent fun
Child#16f65612
parent fun
Why the line this.fun() is not giving compile-time error?
I think fun is a private member in Child class and therefore can't be accessed from outside the Child class(from public member of it's Parent class).
Why Parent class version of fun() is being called by this.fun()? Note this refers to child class object.

Private members are not inherited.
I think this might be the key point that you are missing here. What this means is that Child.fun does not override Parent.fun. They are just two plain old methods that has nothing to do with each other.
When you call accessFun, control always goes into this bit of code in Parent:
public void accessFun(){
System.out.println(this);
this.fun(); <---- here
}
Now, since we are now inside Parent, we can access fun. And since Parent.fun is not overridden, it calls Parent.fun and not Child.fun.
I think fun is a private member in child class and therefore can't be accessed from outside the class(may even from public member of it's Parent class).
That is a complete misunderstanding. if private members can't be accessed from outside of the class, not even through public methods, then they will be much less useful. Why even have them in the first place?
"Private members can only be accessed by members declared in the same class" is probably a better thing to remember.

private fun() in Parent is called by public accessFun() of same Parent class. And public accessFun() is called in main() of Test class.
Here accessFun() is public so it can be called from any where.
For example just like Pojo classes private members are accessed through public setters and getters

The fun method in parent is private and the child fun() method is not overriding the parent fun() method. But the accessFun method is public so it can be called from the child class and is publicly accessible.
So when you call accessFun() method it will be calling the parent class fun() method. Not the child class fun() method as it is private. That is why you wont get an error.

I think fun is a private member in child class and therefore can't be accessed from outside the class(may even from public member of it's Parent class).
Sometimes everything comes from "outside". The main call comes from outside for example.
If a private member can not be accessed from outside, it would always be dead code and this makes no sense.
The difference is the understanding from direct-access and indirect-access.
In all cases you call the method non-directly via the method accessFun().

Related

Question regarding result of "No late binding for static methods" [Java]

Given the code from Parent class and Child class:
class Parent{
public static void classMethod(){
System.out.println("ClassMethod in Parent");
}
public void hello(){
System.out.println("Hello from parent, call classMethod");
classMethod();
}
}
class Child extends Parent{
public static void classMethod(){
System.out.println("ClassMethod in Child");
}
}
If I have this in main method:
public static void main(String[] arg) {
Parent D = new Child();
D.hello();
}
Why is this the result? ->
Hello from parent, call classMethod
ClassMethod in Parent
So there's a child object of parent class calling an instance method which calls a static method.
I would understand why it calls the static method from the parent class if hello() was static as well, since the object type would be defined at compile time and it would be Parent. However, since hello() here is an instance method, it has to be resolved at runtime, and at runtime, isn't the type of the object the actual type, AKA Child type? So in that case, wouldn't it call the static method from the child object since the object is of child type at run time?
Note: this answer assumes the Child class extends Parent. Otherwise, the code in the main method just throws an error.
This is an example of up-casting and polymorphism. Because it's of the type Parent, its access is limited to the Parent class. When you call the hello() method, it is being called in the Parent class. Then, this method calls classMethod() but, because hello() is a method in the parent class, it calls it in the Parent class as well, which is why you are getting that as a result. The fact that it is static makes no difference: static methods can always be called by instance methods, but not always the other way around.
One thing I should point out is that, because of the line Parent D = new Child();, the object D does not actually have access to any of the static methods in Child even though it is that type. If you wish for D to have access to methods in both Parent and Child, you can use Child D = new Child();
With Parent D = new Child();, if you are calling a method, it must be in the Parent class and will run the method in the parent class - except for if there is an overriding instance method of the same name in the Child class, in which case it will run this method instead. It should also be noted that an overridden method cannot be static

Why this code doesn't call the subclass? Inheritance in Java

public class Parent {
public void printParent()
{
System.out.println("I am the Parent");
System.out.println("----this is ::---" + this);
this.printChild();
}
private void printChild()
{
System.out.println("This is my child");
}
}
public class Child extends Parent {
private void printChild()
{
System.out.println("I am the child");
}
}
public class RelationshipTester {
#Test
public void testRelation()
{
Child parent = new Child();
parent.printParent();
}
}
This is the output :-
I am the Parent
----this is ::---datastructures.lists.inheritance.Child#1a692dec
This is my child
The object is of the type Child , yet it doesn't call the child method and the parent one. I have given this.printChild();
In the Parent class, you have declared printChild as private ... and called it. A private method cannot be overridden. Your printChild in the Child class is not known to the Parent class.
If you were to change the private modifier to public, then you would have an override, and your example should output what you are expecting.
Why won't Java let you override a private method? Well, basically, if you could do it then there would be no way to write a class with an abstraction boundary that a child class could not break. That would (IMO) be a major language design short-coming.
Why doesn't Java report an error or warning? Well there is no error because this is legal Java according to the JLS. As for a warning ... if you compile Parent in isolation there is no problem, because the code as written is declaring and using a private method. If you compile Child in isolation, the compiler can't see the private method in the Parent class. (Indeed, it may not even exist in the version of the .class file for Parent that you are compiling against.) Only if you compiled Parent and Child at the same time might the compiler spot something a bit odd.
The keyword 'this' point to the current class instance and here is the private void printChild(). And then you have created an object of class Child at RelationshipTester class. The scope of the two function is private which means to is bounded to that class only. Thus, it won't overwrite the subclass and would execute the Base class's method.
private methods are not inherited. When you call printParent, you're calling a method on Parent and when that method refers to this, it's referring to an instance of that class (Parent), which has its own printChild method. Making Parent#printChild a protected method should give the expected result.
public class Child extends Parent {
protected void printChild(){
System.out.println("I am the child");
}
}
use protected, not private
In this program we have to remember 2 points:
If we create an object for a subclass (here child) then memory also created for the super class. That means if the method that we are calling that is not found in the child class then Java Virtual Machine goes to parent class and checks for the method that we are calling and if the method is found it will execute. If the method is found in child class itself it will not go to the parent class.
private, static and final methods can't be overridden.
Since the scope of the method is private it is not visible to other class.

Why do child classes cast to parent type default to parent version of private instance methods, but not of other instance methods?

It was my understanding that a child cast to the parent type (as in Super sc = new Child();) would call the parent class's static methods, and access the parent class's non-hidden fields, but would make use of the child class's instance methods.
This does not seem to hold true for the case of private instance methods (those in which overriding does not actually take place because the parent method is private.)
I understand that the fact that there is no overriding (private parent methods are not visible to the child, so they can only be hidden.) would mean that the child wouldn't look up the heirarchy to see the parent's version of the method when the instance method is invoked from the child.
However, the exact opposite of what I'd expect (the version present in the child being called) is occurring. The parent version of the private method is invoked.
Why does this happen if the instance methods of the child are typically invoked, and within the child, there is a method with an identical signature (a perfect match for the invocation of method2() in this case) already present, hiding the same method in the parent class?
package whatever;
public class A {
public void method1(){
System.out.println("A method1().");
}
//using "final" here to emphasize that this is a hiding, not an override.
private final void method2(){
System.out.println("A private method2().");
}
public static void main(String[] args)
{
A a = new A().new B();
a.method1(); //calls B method 1
((A.B)a).method1(); //calls B method 1
a.method2(); //calls A private method 2 **I expected it to call B private method 2
((A.B)a).method2(); //calls B private method 2
}
public class B extends A {
public void method1(){
System.out.println("B method1().");
}
private final void method2(){
System.out.println("B private method2().");
}
}
}
First, B is actually a nested class and, oddly enough, the private members of nested classes can by accessed by the outer class. Otherwise, it wouldn't even be legal to do ((A.B)a).method2(); (The reverse is also true. B can access private members in A as well.)
That said, to answer your actual question, the reason a.method2(); calls the private method in A is that private methods are not virtual, as they cannot be overriden at all. (How could they be, if inheriting classes aren't supposed to even know about them?) As such, they are bound at compile time, which means using the declared type of the variable. A a is declared as A, but (A.B)a is cast at compile time to B. Thus, your first call uses the private method from A and your second call uses the private method from B.
It's quirky that the facts in those two paragraphs don't interact with each other. It might reasonable to expect that, since the nested class "knows" about the outer class's private members, an override might be possible. But it's not. Private functions never show up in the vTable and can never be overridden.
Short answer: because your B class is in the same file (.java) with the one that contains #main() method.
The reason that the private method of the parent class is visible to the child class is that the child class is an inner class of its parent class in your case.
Non-static nested classes (inner classes) have access to other members of the enclosing class, even if they are declared private

Java inheritance: Reducing visibility in a constructor vs inherited method

In the following code, the constructor of Child has reduced visibility from public to private, which is allowed. The inherited methods, such as test(), cannot have reduced visibility. Why does Java operate this way?
class Parent {
public Parent(){}
public void test()
{
System.out.print("parent test executed!");
}
}
class Child extends Parent{
private Child(){}
private void test(){
System.out.print("child test executed!");
}
}
Constructors are not inherited, so Child() doesn't override Parent().
As for the methods, if you have (if Child() were public)
Parent p = new Child();
p.test();
Had it been allowed, this would be invoking a private method. So narrowing the access while overriding is not permitted.
When extending a class you are stating that your class is an extension of the parent class ("IS-A" relationship). What this means is that your class will have all methods of your parent class. This is the same as implementing an interface in java except you gain the method definitions (and fields) from your parent and not just methods declared in the interface. In interfaces constructors are not present because they are not methods. Constructors are special as they belong entirely to the class they are declared on. They declare how to construct only themselves.
In order to construct an object you must know that objects class.
class A {
private message;
private A() {
message = "You created an A";
}
public A(String message) {
this.message = message;
}
public void printMessage() {
System.out.println(message);
}
public static A createAnA() {
return new A();
}
}
class B extends A {
public B() {
super("You created a B");
}
}
A anA = new B(); // This will work
A anotherA = new A(); // This is not allowed as the constructor is private
A yetAnotherA = A.createAnA(); // This works too
So when we constructed B we can say that it is an A. Even though the constructor A is private this is due the constructor not being a part of the interface. The only thing we are saying about B when we assign it to a field of type A is that it has the methods of declared in A. In this case printMessage and createAnA.
That is why you can make the constructor private without changing the definition of the class. Now, why are you not allowed to make the method private when overriding a parents signature. This comes to having varying definitions of the [class].method(). Let's say that you could make your method private. Let's say that you declared a printMssage in the B class. Your reasoning is that you want that method for your use only inside the method and you want your parents printMessage to be used when called externally. Now, you wrote a method like this in the B class.
public void adjustMessage(String additional) {
message = getMessage() + additional();
}
Which version of get message would be executed? Your private one or the public one of your parents? The Java dispatcher would of course choose the public one as it is the one declared in the interface. So we we look at this example we can see if you did make your method have different a lower privilege your method could never be dispatched too which would just make things confusing for the reader.
This is a very good question.

Calling a parent's inner class in a super call Java

So, I ran into a wall earlier. If I have a class Parent with an inner class SubParent like this:
public class Parent
{
public class SubParent
{
}
public Parent(SubParent sp)
{
}
}
Then I have a Child class which extends Parent like this:
public class Child extends Parent
{
public Child()
{
super(new SubParent());
}
}
Then I get a "error: cannot reference this before supertype constructor has been called" with an arrow pointing at the SubParent constructor.
Now, if I have SubParent as a separate class in it's own file, everything is fine. But I would like to have it as an inner class. Is there any way to do that?
An inner class instance requires an outer class instance to exist. At the point you are calling
super(new SubParent());
the SubParent constructor would have been called before an outer class instance has been created. You can't do this.
Either declare SupParent in its own file or make it static. What relationship are you trying to achieve anyway?
Since your SubParent is not a static nested class, there's an implicit relationship between it and the Parent object it belongs to (in this case, also a Child object). It sounds like you're not needing the relationship an inner class provides; try making SubParent a public static class.
Note that there's a distinction between an inner class, which is not static (has a reference to an instance of its containing class), and a nested class, which is any class contained inside another class, whether static or not.
Your problem is that you are trying to create a SubParent very early in construction of the Child, before it is ready to use as "this" in an inner class creation. In addition to earlier suggestions, you could change Parent to have a parameterless constructor and a setter for its SubParent reference:
public Parent(){
}
public void setSub(SubParent sp){
}
The Child constructor can wait until after the super call to create the SubParent:
class Child extends Parent
{
public Child()
{
setSub(new SubParent());
}
}

Categories

Resources