I have the following code. Two questions follows:
class Parent {
private void test()
{
System.out.print("test executed!");
}
static void print(){
System.out.println("my class is parent");
}
}
class Child extends Parent
{
static void print(){
System.out.println("my class is Child");
}
}
public class Inheritence {
public static void main(String[] args)
{
Child p1 = new Child();
Parent p = new Child();
System.out.println("The class name of p is "+p.getClass());
System.out.println("The class name of p1 is "+p1.getClass());
System.out.println("p instance of child "+ (p instanceof Child));
System.out.println("p1 instance of child "+ (p1 instanceof Child));
//p.test();
p.print();
}
}
The output is:
The class name of p is class Child
The class name of p1 is class Child
p instance of child true
p1 instance of child true
my class is parent
I thought the classname for p will be Parent, since it is of type Parent. However, it prints as Child. so how would I get the type of p.
Second question here is whether private methods are inherited or not. while many articles including this, comments that private methods are not inherited, I see in the below example it is inherited. It could be some type casting issues below.
class Child1 extends Parent1
{
}
public class Parent1 {
private void test()
{
System.out.print("test executed!");
}
public static void main(String[] args)
{
Parent1 p = new Child1();
p.test();
Child1 c = new Child1();
//c.test(); The method test from parent1 is not visible
}
}
Output is : test executed!
here I am calling test method on Child1 object which is of type Parent1. Child1 has no test method since it is not inherited. but I still get the output, which indicates the private methods are inherited! If test was a protected method, and I override in child class, it is the overridden method that gets executed though the type of object on which it is called is parent(parent p1 = new child1());
EDIT: After few comments, I made class Parent1 and class Child1 seperate and a new Class called App that constructs a parent and child object. now I cannot call p.test in the code below.
class Child1 extends Parent1
{
}
class Parent1 {
private void test()
{
System.out.print("test executed!");
} }
public class App1{
public static void main(String[] args)
{
Parent1 p = new Child1();
p.test();//The method test from parent is not visible
Child1 c = new Child1();
//c.test(); //The method test from parent1 is not visible
}
}
To address the second question: it may be helpful to keep the concepts of "inheritance" and "visibility" distinct. A
privatemethodmis only visible inside the classCwhere the method is declared. So you can't usemat all from outsideC. Furthermore, even insideC, you can't usex.m()unless the objectxis declared to be of typeC. But objects of a subclass still have the methodm, and that method can be called, but only insideC. This example will compile (even if the two classes are in separate files):Note that inside
doThis, you can still call thetestmethod ofc, even thoughchas typeClass2. However, you can do this only because the code is inside the classClass1that declares thetest()method (which is why [2] doesn't compile); and you can do it only by castingcto an object of typeClass1(which is why [1] doesn't compile). However, even after you cast it so that the compiler sees it as an expression of typeClass1, the actual object still has typeClass2. And if you were to call an overridden methodpolymorphiclike this:((Class1)c).polymorphic(), it would call the method defined inClass2, notClass1, since the object is still actually aClass2object.So I think that in some sense,
testis inherited even though it's private; it just isn't visible inClass2.MORE: I think it's also helpful to understand that there's a difference between a compile-time type and a run-time type (or instance type). If you declare a variable
Parent x;thenx's compile-time type isParent. If you have a functionfwhose return type isParent, then an expression likeobj.f(arg,arg2)will have typeParent. But at run-time, if a variable or expression has compile-time typeParent, the actual type at run-time can beParentor any of its subclasses. The run-time type will be based on how the object was constructed. So a variable can have a compile-time typeParentand a run-time typeChild. Then you just need to know which type is used and when. For checking whether a method is visible (which is whereprivatecomes into play), the compile-time type is used. For deciding which method to call when a child subclass overrides a method, the run-time type is used (that's what polymorphism is). For.getClass(), the run-time type is used. Anyway, that's how I think about things so that I don't get too confused.EXAMPLE: Let's say we have:
In some other class, we have
The variables
x1,x2, andx3all have a compile-time type ofParent. This means all three variables could refer to an instance ofParent, or an instance ofChildorGrandchildor any other subclass ofParent. And that's what happens above:x2will refer to an instance ofChild, andx3will refer to an instance ofGrandchild.Similarly:
x5refers to an instance ofChild, andx6refers to an instance ofGrandchild.But the compile-time type of all the variables and the
getAParentcalls is stillParent. The compiler does not know what class the variable or function call actually refers to when you run the program. So if you declare a methodplay()insideGrandchild, these are still illegal:because the compiler thinks of the two variables and
getAParent(2)as having typeParent, notGrandchild. Andplayisn't defined forParent. To see if those variables have a run-time type that has aplaymethod would require the compiler to generate code to check at run-time, and the compiler doesn't do that.That's why
p.test()works in your second example. Even thoughprefers to an instance ofChild1,p's compile-time type isParent1since you declared it as having typeParent1. And the compiler sees thatParent1has atestmethod; and since the code is insideParent1, thetestmethod is visible even though it's private. That's why it works. The compiler doesn't generate code to check what run-time typepactually refers to. Hope this helps explain things.