This question already has answers here:
Hiding Fields in Java Inheritance
(2 answers)
Closed 6 years ago.
So I have the following code :
class Super {
private String name="super";
public String name(){
return this.name;
}
}
class Sub extends Super {
private String name = "sub";
}
public class Main {
public static void main(String[] args) {
System.out.println(new Sub().name());
}
}
what I get is as result is : super .
I wasnt to know why ?! Isn't the method name() supposed to call this of the object that was called from and since Sub extends Super then it should be able to use it on its members ?!
You're probably thinking that the name member field in Sub should be overriding the name member field in Super. It does not: fields cannot be overridden in Java. Moreover, you've defined both fields as private, meaning that member is only visible to other members of that class (and not members of derived classes or of other classes). So in your code, Super has its own private definition of the name field, and Sub has its own completely different private definition. Neither is aware of the existence of the other.
Standard practice in Java is to use getters and setters to access internal data. If need be, you are then free to override it in derived classes.
Related
This question already has answers here:
Why doesn't Java allow overriding of static methods?
(22 answers)
Closed 6 years ago.
public class Base {
private static boolean goo = true;
protected static boolean foo() {
goo = !goo;
return goo;
}
public String bar = "Base:" + foo();
public static void main(String[] args) {
Base base = new Sub();
System.out.println("Base:"+ base.foo());
}
}
public class Sub extends Base {
public String bar = "Sub:" + foo();
protected static boolean foo() {
return false;
}
}
Why the output is "Base: true"? foo() seems to be an overriding method so dynamic type is Sub, than why the return output isn't "false", and also the field of Base has a string, shouldn't there be its output?
In java, you can not override the static methods, If you redefine that static method of super class method in sub class then it becomes method over-written(method hiding), not overriding.
In your example, you are invoking it with the super class ref(base) so the super class method only invoked not the sub class method. so the output is "Base: true"
If you change it with non static method then the sub class method will be executed.
Here the rule is: super class ref and sub class object will work for non static methods.
When you are dealing with the word "static" in terms of a method or a variable, it refers that the method or a variable belong to the "class" and not its object.
When there is no object, there is no overriding.
In your class Base, you declared the main() method, in which you wrote the following statements.
Base base = new Sub();
System.out.println("Base:"+ base.foo());
Now, the reference variable type is Base and the object type is Sub. Since foo() is a static method it belongs to the class of which the reference variable is declared (i.e. Base).
Therefore, foo method of class Base is called.
Method overriding is used to override the behaviour of an object for a subclass and is not applicable for static methods. There is no reason to support this feature for static methods. Moreover, you don't need to create an object to access a static method. You can simply refer it by its name[foo()] or use classname as a prefix[eg: Sub.foo()].
As far as why true is being returned in an output is concerned , this is because you have already used below statement in your class , which invokes foo() method
public String bar = "Base:" + foo();
Since goo is a static variable, only one instance of this variable is maintained for this class . And on execution of above statement , the value of goo changes to false(goo=!goo,goo initially being true).
Later on , when you use base.foo() , foo() of base class will be executed [As method overriding not applicable for static methods and Base class reference is being used] which again reverts the value of goo making it true.
I searched a lot. The difference between them is that override is for the instance method and hidden is for the static method. And the hidden is in fact the redefinition of the method. But I still don't get it.If redefinition means that the static method of parent still exists in the subclass, it is just we can't see it? Or why we call it hidden but not any other words? But if it exists, I can't find a way to call the method again. To be honest from a function level I can't find why they are different. Can some one explain it from a deeper level such as memory?
Static members(methods and variables) will not be present in the sub class(Child class) object which inherit them but they'll be present as a single copy in the memory.
Static members can be accessed by the class name of both Super class and sub class but they are not physically present in the object of these classes.
Where as when you inherit non-static members, Sub class object in memory will contain both inherited methods as well as the methods of its own. So when you try to write a similar method here, super class method will be overridden. On the other hand as static methods does not participate in inheritance, any similar method you write that is present in super class, new method will run every-time it is asked for. Parent class method is just hidden but not overridden!
From JLS 8.4.8.2, example 8.4.8.2-1 shows us that a hidden method binds to the type of the reference (Super), while an overriden method binds to the type of Object (Sub).
class Super {
static String greeting() { return "Goodnight"; }
String name() { return "Richard"; }
}
class Sub extends Super {
static String greeting() { return "Hello"; }
String name() { return "Dick"; }
}
class Test {
public static void main(String[] args) {
Super s = new Sub();
System.out.println(s.greeting() + ", " + s.name());
}
}
Output:
Goodnight, Dick
If you call Superclass.staticMethod() you will get the method as defined on the superclass, regardless of any hiding taking place in subclasses. On the other hand, if you call ((Superclass)subObj).instanceMethod() you'll still be calling the method as it is overridden in the subclass.
I have the following code snippet that attempts to use this and super.
class SuperClass
{
public final int x=10;
public final String s="super";
public String notOverridden()
{
return "Inside super";
}
public String overrriden()
{
return "Inside super";
}
}
final class SubClass extends SuperClass
{
private final int y=15;
private final String s="sub"; //Shadowed member.
#Override
public String overrriden()
{
return "Inside sub";
}
public void test()
{
System.out.println(super.notOverridden());
System.out.println(this.notOverridden());
System.out.println(this.overrriden());
System.out.println(super.overrriden());
System.out.println(this.s);
System.out.println(super.s);
System.out.println(this.x);
System.out.println(super.x);
System.out.println(this.y);
}
}
public final class Test
{
public static void main(String[] args)
{
SubClass subClass=new SubClass();
subClass.test();
}
}
In this simplest of Java code, the statements that redirect the output to the console inside the method test() within the class SubClass display the following output.
Inside super
Inside super
Inside sub
Inside super
sub
super
10
10
15
So, it appears that there is no difference between this and super, when they are used to access methods which are not overridden in its subclass(es) and in case of variables, when they are not shadowed in its subclass(es).
Both of them tend to point to super class members. There is however, an obvious difference, if such is not a case.
Are they same, when methods are not overridden or variables are not shadowed in respective subclasses?
So, it appears that there is no difference between this and super,
when they are used to access methods which are not overridden in
its subclass(es) and in case of variables, when they are not
shadowed in its subclass(es).
There is a difference. If you override methods in third class, and call test from it, you will see, that super still calls implementations of SuperClass. And this will call new implementations (overridden).
Addition:
this.method() usage implies the method belongs to instance of the object. So the last implementation will be used (with exception of private methods).
super.method() usage implies method of the instance, but implemented before the current class (super, or super.super etc).
Yes, they are the same. notOverridden methods and not shadowed variables are inherited by subclass.
To better understand this, knowing how object is located in memory is helpful. For example in the figure below. Assume it's an object of a subclass. The blue area is what it inherits from its parent, and the yellow area is what is defined by itself. The method has the similar design except that it uses a Vtable.
Child object has the same memory layout as parent objects, except that it needs more space to place the newly added fields. The benefit of this layout is that a pointer of parent type pointing at a subclass object still sees the parent object at the beginning.
I was told that for a Java subclass it can inherit all members of its superclass. So does this mean even private members? I know it can inherit protected members.
Can someone explain this to me. I am now totally confused.
No, the private member are not inherited because the scope of a private member is only limited to the class in which it is defined. Only the public and protected member are inherited.
From the Java Documentation,
Private Members in a Superclass
A subclass does not inherit the
private members of its parent class.
However, if the superclass has public
or protected methods for accessing its
private fields, these can also be used
by the subclass. A nested class has
access to all the private members of
its enclosing class—both fields and
methods. Therefore, a public or
protected nested class inherited by a
subclass has indirect access to all of
the private members of the superclass.
From the JLS,
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.
A useful link : Does subclasses inherit private fields?
This kind of depends on your exact usage of the word inheritance. I'll explain by example.
Suppose you have two classes: Parent and Child, where Child extends Parent. Also, Parent has a private integer named value.
Now comes the question: does Child inherit the private value? In Java, inheritance is defined in such a way that the answer would be "No". However, in general OOP lingo, there is a slight ambiguity.
You could say that it not inherited, because nowhere can Child refer explicitly to value. I.e. any code like this.value can't be used within Child, nor can obj.value be used from some calling code (obviously).
However, in another sense, you could say that value is inherited. If you consider that every instance of Child is also an instance of Parent, then that object must contain value as defined in Parent. Even if the Child class knows nothing about it, a private member named value still exists within each and every instance of Child. So in this sense, you could say that value is inherited in Child.
So without using the word "inheritance", just remember that child classes don't know about private members defined within parent classes. But also remember that those private members still exist within instances of the child class.
You will be satisfied here 100%. I tested it on my computer and what I concluded I'm going to post it here. Just go through the program written below, see the program output and READ THE CONCLUSION given at the end.
To test it yourself, copy the whole program and save it in a file named "InheritanceTest.java" then compile it and finally run it.
Program
// Testing if a subclass can access the private members of a superclass
class Class1 {
private String name;
public void setName(String name) {
this.name = name;
System.out.println("The name has been set successfully.");
}
public void showName() {
System.out.println("The name is: " + name);
}
}
class Class2 extends Class1 {
private int age;
public void setAge(int age) {
this.age = age;
System.out.println("The age has been set successfully.");
}
public void showAge() {
System.out.println("The age is: " + age);
}
public void displayName() {
//Accessing the private member of superclass here
//System.out.println("The name is: " + name); //error, can't compile because access to the private member name of the superclass Class1 is not permitted here.
}
}
class InheritanceTest {
public static void main(String[] args) {
Class1 c1 = new Class1();
Class2 c2 = new Class2();
c1.setName("Name_C1");
c2.setName("Name_C2"); //No error, setName() is a public member of the superclass which indirectly gives access to the private member "name".
c1.showName();
c2.showName(); //No error, showName() is a public member of the superclass which indirectly gives access to the private member "name".
c2.setAge(25);
c2.showAge();
//c2.displayName(); //error
}
}
Output
The name has been set successfully.
The name has been set successfully.
The name is: Name_C1
The name is: Name_C2
The age has been set successfully.
The age is: 25
Conclusion
Yes, a subclass can indirectly access the private members of a superclass. A subclass can't directly access the private members of a superclass.
All the public, private and protected members (i.e. all the fields and methods) of a superclass are inherited by a subclass but the subclass can directly access only the public and protected members of the superclass. If an inherited member from a superclass gives access to a private member of the superclass then the subclass can use this inherited member to access the private member of the superclass.
IMO by no way is it a matter of definition. In class-based Inheritance implies propagation of behavior to descendants. As such private members DO get inherited , and I will not go into the details how this happens.
Actually I find the "not inherited" answer to be dangerous for new developers and they do not comprehend right away that the private members are there hidden under the skin of your class and they (can) have severe impact on its behavior, size of the objects etc.
It is common that "development comes before understanding" in computer science, however lets avoid building (or destroying) our conceptualization of OOP assuming the wrong "definition" adopted by some technician writing the manual of a well known class based OO platform.
Sorry for stating something in such an old post, but the issue is always valid.
Though https://docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.2 shows that Private Members are not inherited. Actually, it is inherited by subclass. When we use debuggers to trace variables, it will show the private members under the label of "inherited", so just try it. there is another post discussing this question, and most of them think not inherited, which misleads many people, including me at first.
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Why can't you reduce the visibility of a method in a java subclass?
How come I can override a private method in superclass with a public when in a subclass, but I cannot override a public method in the superclass into private method in subclass?
Why?
Thank you in advance.
Overriding a method can't ever reduce the visibility. Allowing that would violate the Liskov Substitution Principle, which states (simplified) that all objects of a derived class B must have the same properties as the base class A. In this case one such "property" would be a public method foo which would be "lost" if B had that same method, but made it protected.
Also, since private methods are not inherited (try calling it from a derived class!) they can't ever be overriden. You can have a public method with the same name as a private one in the base class, but that's not overriding, it's simply a new method with the same name, but not other relation. Calls to the private method in the base class will not call the public method in the superclass, even when executed on objects of the superclass!
In other words: private methods never use runtime polymorphism.
See this sample:
public static class Base {
public void callBoth() {
foo();
bar();
}
private void foo() {
System.out.println("Base.foo");
}
protected void bar() {
System.out.println("Base.bar");
}
}
public static class Sub extends Base {
public void foo() {
System.out.println("Sub.foo");
}
public void bar() {
System.out.println("Sub.bar");
}
}
When executing new Sub().callBoth() the output will be this:
Base.foo
Sub.bar
Because it doesn't break the class contract to make a method more available. If Kitten subclasses Animal, and Animal has a public method feed(), then Kitten must also have a public method feed(), as it must be possible to treat any instance of Kitten like an instance of Animal. Redefining the access level to private would break that.
If the public method became private, then it would not be possible to up cast the instance into its parent class (because one of the methods would be unavailable).
If the private method became public, then it would be possible to up case the instance into its parent class (because then you would just have no way to grab the private / publicly overriden method).
The access level can't be more restrictive than the overridden method.
private-->[default]-->protected-->public
By overriding you're saying that your subclass can be called with the same api but may function differently. Making something public increases the access level - so you're not removing guaranteed functionality.
By making a public method private (if you could actually do this) you'd be removing functionality, so breaking the "contract". It also doesn't make sense in that the method could still be called publicly, it's just that the public call would access the public method in the superclass, which would be counterintuitive.