This is a code sample of inheritance while the code functions fine.I am unable to understand the output of this code kindly explain it to me.
class R {
private void S1() {
System.out.println("R:S1");
}
protected void S2() {
System.out.println("R:S2");
}
protected void S1S2() {
S1();
S2();
}
}
class S extends R {
private void S1() {
System.out.println("S:S1");
}
protected void S2() {
System.out.println("S:S2");
}
}
public class Inheritance {
public static void main(String srgs[]) {
new S().S1S2();
}
}
The output is:
R:S1
S:S2
Why is the first call made to,R class' S1 while second to S class' S2.
R.S1 is private, so it's not called polymorphically, and S.S1 doesn't override it.
R.S2 is protected, so S.S2 overrides it, and when you call S2 on an instance of S2 (even if it's only statically known to be an instance of R), S.S2 will be called.
From section 8.4.8.1 of the JLS:
An instance method m1, declared in class C, overrides another instance method m2, declared in class A iff all of the following are true:
C is a subclass of A.
The signature of m1 is a subsignature (§8.4.2) of the signature of m2.
Either:
m2 is public, protected, or declared with default access in the same package as C, or
m1 overrides a method m3 (m3 distinct from m1, m3 distinct from m2), such that m3 overrides m2.
Note how m2 can't be private.
In R, S1 is private and so cannot be overridden. The call to S1 in R#S1S2 therefore always calls R#S1. The S1 in S is totally unrelated. [Side note: you need better names.]
But S2 is not private so it can be overridden - and it is.
Java VMs can get good performance gains out of knowing that private functions cannot be overridden. And nothing, not even a descendant class, should be affected by the private details of a class.
Related
public class Shape
{
final private void print()
{
System.out.println("in class Shape");
}
public static void main(String[] args)
{
Shape shape=new Rectangle();
shape.print();
//calling shape class function
//giving output in class shape
}
}
public class Rectangle extends Shape
{
public void print()
{
System.out.println("in class Rectangle");
//super.print();
}
}
Ques: why private function don't show polymorphic behaviour ?
and we are still overriding final method?
its calling base class funtion why?
A Private function is not visible nor callable from its children; hence these are two completely different functions. There is nothing to overwrite from the perspective of the child class, because it is not aware that the parent even has a print() function.
Making it final private void print() is to prevent it from overriding in sub-classes.
As final prevents overriding and private makes the method invisible to the sub-classes so that it cant be accessed
See also :
Java `final` method: what does it promise?
Overriding private methods in Java
You are not actually over-ridden the print method because of private. They are completely different.
More over you cannot override a final method.
This is the place where #override annotation helps you better. If you try to place the annotation, then you realize the behaviour at compile time itself.
In addition to Eriks answer from the Java Language Specification:
A class C inherits from its direct superclass all concrete methods m (both static and instance) of the superclass for which all of the following are true:
m is a member of the direct superclass of C.
m is public, protected, or declared with package access in the same package as C.
No method declared in C has a signature that is a subsignature (§8.4.2) of the signature of m.
and
An instance method mC declared in or inherited by class C, overrides from C another method mA declared in class A, iff all of the following are true:
[...]
One of the following is true:
mA is public.
mA is protected.
So your subclass doesn't inherit the private methods, hence there is nothing to override.
Polymorphism is the capability of an action or method to do different
things based on the object that it is acting upon. In other words,
polymorphism allows you define one interface and have multiple
implementation. This is one of the basic principles of object oriented
programming.
The method overriding is an example of runtime polymorphism. You
can have a method in subclass overrides the method in its super
classes with the same name and signature. Java virtual machine determines the proper
method to call at the runtime, not at the compile time.
But if you will think as print() is instance method and at runtime why it is not calling from Rectangle print() method.
The reason is as print() of subclass is not a overriden method as parent class method is final which cannot be overriden.
Shape shape=new Rectangle();
shape.print(); // prints in the shape class
((Rectangle)shape).print(); //prints in the rectangle class
As parent's class method is private so it is not visible for outside world and as it is final it cannot be overriden.
In your example it is shown as private final method so this method is not visible out side the class. So Rectangle can't see the method defined inside Shape class.
public class A{
final private method1(){
}
final public method2(){
}
public method3(){
}
}
public class B extends A{
public method1(){
//it is legal. but it is not a override. this method can't see the method1 defined in A
}
public method2(){
//throw error. because final method can't be overriden
}
public method3(){
//legal override method
}
}
To my understanding, the following code should print a as per my knowledge of run time polymorphism.
However, when I run the following code it is printing b:
Per JLS 8.4.8.1, B1.m1 does not override A1.m1, and so when A1.m1 is
invoked, B1.m1 should not be selected
package a;
public interface I1 {
public Object m1();
}
public class A1 {
Object m1() {
return "a";
}
}
public class C1 extends b.B1 implements I1 {
public static void main(String[] args) {
a.A1 a = new a.C1();
System.out.println(a.m1());
}
}
package b;
public class B1 extends a.A1 {
public String m1() {
return "b";
}
}
Can some one help me understand this behavior.
After adding the packages, the question is much more difficult. I've tried this, and I changed your main program to
public class C1 extends b.B1 implements I1 {
public static void main(String[] args) {
a.A1 a = new a.C1();
System.out.println(a.m1());
a.A1 b = new b.B1();
System.out.println(b.m1());
}
}
(I actually used different package names to avoid conflicts with the variable names. So my code looks a bit different from the above.)
I've confirmed that this prints "b" and "a". That is, if I create a new B1, its m1 method does not override the one in A1. Thus if I print b.m1(), since b is of type A1, polymorphism doesn't kick in, and the method declared in A1 is called. So what's going on with C1?
C1 inherits the m1 method from B1. But even though the m1 method in B1 doesn't override the one in A1, the m1 method in C1, which it inherits from B1, actually does override the one in A1. I think it has to do with this clause in 8.4.8.1:
mA is declared with package access in the same package as C, and either C declares mC or mA is a member of the direct superclass of C.
Here C is your C1 class. mC is the m1 that's inherited from B1. In this case, "C declares mC" is false, because C1 doesn't declare m1, it inherits it. However, I believe "mA is a member of the direct superclass of C" is true. As I understand it, B1 has all the members that A1 has. B1 declares its own m1, and since it's not overriding, it's a new m1 that causes the m1 it inherits from A1 to be hidden. But even though it's hidden, it's still a member. Thus the condition that mA is a member of the direct superclass of C (which is B1) is satisfied, and thus all the conditions of 8.4.8.1 are satisfied and thus the inherited m1 in C1 overrides the one in A1.
The expected output is indeed b.
When you declare your object a as being of the type A1, that class defines only the interface of the methods. It defines that m1 returns a String, but the implementation of that method is defined by the Class used to build the object, which is Test1. And Test1 extends B1, which overrides the method m1, so that is the implementation of m1 used for your object.
The output of that call m1() must be indeed the B1's.
EDIT: This answer was written for the first version of the question. OP changed a lot of the code, but the root of the explanation is still the same.
The following line A1 a = new Test1(); simply means build a Test1 instance and store it in a A1 box.
So the instance will be a Test1, but you will only have access to the method/variable of A1, but every overriden method in Test1 will be accessed.
This is polymorpish.
By reading the JLS about 8.4.8.1. Overriding (by Instance Methods) about the accesor
An instance method mC declared in or inherited by class C, overrides from C another method mA declared in class A, iff all of the following are true:
A is a superclass of C.
The signature of mC is a subsignature (§8.4.2) of the signature of mA.
mA is public.
You can find more information about the access modifiers in 8.4.8.3. Requirements in Overriding and Hiding
The access modifier (§6.6) of an overriding or hiding method must provide at least as much access as the overridden or hidden method, as follows:
If the overridden or hidden method is public, then the overriding or hiding method must be public; otherwise, a compile-time error occurs.
If the overridden or hidden method is protected, then the overriding or hiding method must be protected or public; otherwise, a compile-time error occurs.
If the overridden or hidden method has package access, then the overriding or hiding method must not be private; otherwise, a compile-time error occurs.
EDIT :
Now, with your package added.
Having C1 to implement m1 (because of the interface), you are hiding the method of A1 with the implementation you find in B1, this method is indeed a valid definition for the interface contract.
You can see you are not overriding the method (you can't call super.m1 or even add #Override on the B1.m1. But the call a.m1() is valid as it is define in the class itself.
You are Overriding. Include the #Override annotation and you can see that. As long as your class extending can override the parent class method, you can increase the access, but not decrease the access.
If you tried to make B#m1 private, then somebody could just cast to an A and use the method.
Conversely, if you make A#m1 private, then B cannot override it and you can end up with an object having two methods with the same signature.
static class A{
private String get(){
return "a";
}
}
static class B extends A{
public String get(){
return "b";
}
}
public static void main (String[] args) throws java.lang.Exception
{
A b = new B();
System.out.println(b.get());
System.out.println(((B)b).get());
// your code goes here
}
This will output:
a
b
All comments and answers are mostly correct. They explain things in term of language mechanisms. I think, instead, that to realise the real meaning of inheritance and polymorphism and how to use them, you have to take a more conceptual approach.
First of all inheritance is a relationship between two things and the relationship is of the type “is a”. In other words when you write the statement class C1 extends B1 you mean C1 is a B1.
Of course this won’t work with A1, B1 and C1. Let me change them in something more real. For example:
A1 = Animal
B1 = Feline
C1 = Cat and C2 = Lion (polymorphism)
At this point you will have class Cat extends Feline, and you can conceptually read it as: Cat is a Feline. I suggest to challenge your inheritance formal correctness using the “is a” test. If it doesn't work, it is better to reconsider or rethink the inheritance.
Your resulting code will be like the following:
public interface IAnimal {
public Object saySome();
}
public class Animal {
Object saySome() {
return "I am an animal";
}
}
public class Feline extends Animal {
public String saySome() {
return "I am a feline";
}
public class Cat extends Feline implements IAnimal {
Object saySome() {
return "meow";
}
}
public class Lion extends Feline implements IAnimal {
Object saySome() {
return "roar";
}
}
class Aplication {
public static void main(String[] args) {
Animal anAnimal = new Cat();
Animal anotherAnimal = new Lion();
System.out.println(anAnimal.saySome());
System.out.println(anotherAnimal.saySome());
}
}
And clearly the output will be
meow
roar
I hope this will help.
You have an interface I1, which is implemented by A1
Class B1 extends A1
Class C1 extends B1 (and therefore implicitly extends A1).
So an instance of C1 is also of type B1, A1 & I1, however it remains an instance of C1 regardless of whether you assign it to one of the other types.
If you have:
I1 instance = new C1();
String value = instance.m1();
The first m1 method going up the inheritance tree from the real type (C1) will be called, which will be in B1 and return "b".
According to the JLS 8.4.8.1
An instance method m1, declared in class C, overrides another instance
method m2, declared in class A iff all of the following are true:
C is a subclass of A.
The signature of m1 is a subsignature (§8.4.2) of the signature of m2.
Either:
m2 is public, protected, or declared with default access in the same
package as C, or
m1 overrides a method m3 (m3 distinct from m1, m3 distinct from m2),
such that m3 overrides m2.
This doesn't appear to contradict the following code:
public class Main {
public void f() { }
public static class A extends Main {
protected void f() { }
}
public static void main(String[] args) {
}
}
DEMO
But it's not compiling, even though the overridden version of the method f() has the protected access modifier, as said in the second point of the rule I provided. What's wrong?
The justification for this is provided lower in the JLS, in 8.4.8.3:
The access modifier (§6.6) of an overriding or hiding method must provide at least as much access as the overridden or hidden method, as follows:
If the overridden or hidden method is public, then the overriding or hiding method must be public; otherwise, a compile-time error occurs.
If the overridden or hidden method is protected, then the overriding or hiding method must be protected or public; otherwise, a compile-time error occurs.
If the overridden or hidden method has default (package) access, then the overriding or hiding method must not be private; otherwise, a compile-time error occurs.
Note that the section you've quoted in your question essentially states "the method's access modifier in the base class must not be private", and doesn't relate to the overriding method's access modifier at all.
You cannot override a method with more restrictive access modifier. The method f() was declared with access modifier public but you are trying to override it with protected modifier which is more restrictive. Change
public static class A extends Main{
protected void f(){ }
}
to
public static class A extends Main{
public void f(){ }
}
I have a following code bellow and i don't understand why the output of this code is: "high high". In my mind the output must be: "Low Out"
public class A{
private String runNow(){
return "High";
}
static class B extends A{
public String runNow(){
return "Low";
}
}
public static void main(String args[]){
A[] a=new B[]{new B(),new C()};
for(A aa:a)
System.out.print(aa.runNow()+" ");
}
}
class C extends A.B{
public String runNow(){
return "Out";
}
}
Since runNow() method in class A is private, it's not overridden at all. So, the output is as expected.
Try adding #Override annotation over the method in class B, and you'll see a compiler error.
private methods cannot be overriden. The rules are described in the Java Language Specification 8.4.8.1. Overriding (by Instance Methods)
An instance method m1, declared in class C, overrides another instance
method m2, declared in class A iff all of the following are true:
C is a subclass of A.
The signature of m1 is a subsignature (§8.4.2) of the signature of m2.
Either:
m2 is public, protected, or declared with default access in the same
package as C, or
m1 overrides a method m3 (m3 distinct from m1, m3 distinct from m2),
such that m3 overrides m2.
When you declare a runNow() method in B and in C, you are simply creating a new method. Try to add #Override to them for kicks. You will get a compiler error
The method runNow() of type A.B must override or implement a supertype
method
In your for loop
for(A aa:a)
System.out.print(aa.runNow()+" ");
you are calling runNow() on variables declared as type A and since you are in the A class you have access to them. There's no polymorphism involved here.
Recently came across an interesting feature, which, though, can result in a unexpected output of Eclipse "add unimplemented methods" feature. What is the "googl-able" name of the language concept behind this "occasional implicit implementation"?
I wouldn't expect the code below to compile but it did and is working
interface CallmeIfc {
public void callme();
}
class CallmeCode {
public void callme() {
// implementation
}
}
class CallmeImpl extends CallmeCode implements CallmeIfc {
// empty class body
}
public static void main(String[] args) {
CallmeIfc me = (CallmeIfc) new CallmeImpl();
me.callme(); // calls CallmeCode.callme()
}
In CallmeImpl, the public callme() method is inherited from CallmeCode, so CallmeImpl respects the contract defined in the CallmeIfc.
Then, in your main() method, polymorphism allows you to assign a subclass instance (CallmeImpl) to a superclass or superinterface reference - in this particular case, the "me" reference, of type CallmeIfc (you have a typo here, BTW).
Actually this looks like a compiler bug to me: The Java Language Specification writes:
An instance method m1 declared in a
class C overrides another instance
method, m2, declared in class A iff
all of the following are true:
C is a subclass of A.
The signature of m1 is a subsignature (§8.4.2) of the signature of m2.
Either
m2 is public, protected or declared with default access in the same package as C, or
m1 overrides a method m3, m3 distinct from m1, m3 distinct from m2, such that m3 overrides m2.
In your case, the first condition is not satisfied: The method callme is declared in class CallMeCode, which is not a subtype of CallmeIfc.
Edit: Bobah is right, the Spec distinguishes between implementing and overriding. In fact, it actually mandates the observed behaviour:
Unless the class being declared is
abstract, the declarations of all the
method members of each direct
superinterface must be implemented
either by a declaration in this class
or by an existing method declaration
inherited from the direct superclass,
because a class that is not abstract
is not permitted to have abstract
methods
The Spec does not explain why.
Although CallmeCode class doesn't implement the CallmeIfc interface, it provides the necessary implementation. It is as if class CallmeCode implements the interface. It would have worked also with this code:
interface CallmeIfc {
public void callme();
}
class CallmeCode implements CallmeIfc {
public void callme() {
// implementation
}
}
class CallmeImpl extends CallmeCode implements CallmeIfc {
// empty class body
}
In your case this is fine because class CallmeCode has a method callme. If the method would have been named different it wouldn't compile.