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.
Related
This is probably answered somewhere, but I have no idea what to search for. Imagine you have the following...
The superclass, Animal.java
public class Animal {
public String noise = "squeak";
public String toString() { return noise; }
}
The subclass, Lion.java
public class Lion extends Animal {
public String noise = "ROAR!!";
public String toString() { return noise; }
}
The main class, Runner.java
public class Runner {
public static void main(String[] args) {
Animal a = new Animal();
System.out.println(a);
System.out.println(a.noise);
Lion b = new Lion();
System.out.println(b);
System.out.println(b.noise);
Animal c = new Lion();
System.out.println(c);
System.out.println(c.noise);
}
}
The output is:
squeak
squeak
ROAR!!
ROAR!!
ROAR!!
squeak
Why does c.noise return squeak? What is the difference between instance method invocation and instance variables that one returns what you'd expect, and the other does not? Why does Java do this?
Thanks
Short answer:
You can override methods, but it's not possible to override fields.
Long answer:
Each class sees the methods and fields of it's own and of it's parents (except for private methods). If the child delcares a method, whose name is the same, as the name of the method in his parent class, this method becomes overridden - if this method is somehow invoked on the child instance (even from the one of the parent's methods), the brand new method will be used instead of the parent's one. Child may still call the original method of his last parent via super.method(...) call.
But the story is different when we come to the fields. If the child declares a new field, that is named exactly as the field in parent class, it will simply hide the parent's field without overriding, just like the local variable hides global one. So the child methods will simply see the child's fields, but the parent's method will continue to see parent's field, and child's field will not be visible by any means from the parent class - that's what you've got.
Child can access the field of it's parent via ((Parent)this).field.
Longer answer:
So really the way you'd do this is define Lion thus:
public class Lion extends Animal {
public Lion() {
noise = "ROAR!!";
}
}
So now for Lion instances the noise member variable of Animal has been updated to ROAR!!
Of course you'd (almost) never actually have a public mutable member on a class like that in the wild.
You can not override fields, new declaration of noise in Lion hides parent's noise attribute. do like this:
public class Lion extends Animal {
// public String noise = "ROAR!!"; // <---- Remove this line
public Lion() {
noise = "ROAR";
}
public String toString() {
return noise;
}
}
All non-static methods in java are by default "virtual functions". Unless they're marked as final (which makes the method not overridable). Java uses a virtual method table to call the correct object's method.
This is because Java talks only about method overriding. Member variables can only be shadowed in child class. So when you say c.noise it actually refers to the string variable in parent class as the c if reference type Animal.
The topics you are interested in are Dynamic Dispatch and Virtual Method Table. Basically, by design, Java allows for methods to be overridden (assuming they are non-final) and at run time the JVM will execute the appropriate implementation. This polymorphic attribute is only afforded to methods. Good OO design would dictate the fields be encapsulated anyway.
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.
As per the link, definition says, The private modifier specifies that the member can only be accessed in its own class.
But the below code is able to access private member item of super class in sub class.
class SuperType {
private int item;
public void setItem(int item){
this.item = item;
}
public int getItem(){
return item;
}
}
public class SubType extends SuperType{
public static void main(String[] args){
SubType s = new SubType();
s.setItem(2);
System.out.println(s.getItem());
}
}
It is also understood that s.itemdoes not work, because item is not a member of SubType class.
How do i understand this definition?
Access modifiers affect direct access to that member.
SubType can get access to item indirectly, through the public getter method, which exists in SuperType and thus has access to the private item member variable.
But SubType can't directly access it, i.e. this is an error if in SubType:
s.item // error; private in SuperType
You have the definition correct and you are accessing a private field by a public accessor and mutator. What you can't do is,
s.item = 2;
which you could if item was public. Also, the fact that SubType is a sub-class of SuperType is irrelevant here. Every class can access item by it's public accessor (and mutator).
You use getter and setters methods to acces/mutate private members in a class. The getters and setters are declared as "public".
You can extend a class and inherit the parent's private members and the getters and setters to access them.
The solution or workaround is to use "Protected" access specifier that allows you to directly access/mutate the properties of a class without any getters and setter. The usage scope is only the package where the class and other classes will be. Protected doesn't require class inheritence. As long as the classes are within the same package, they can access the neighbour's protected members.
A very good explanation has been give in SO in the past - In Java, difference between default, public, protected, and private
public class A
{
public static int i;
}
public class B extends A
{
public static void main(String[] args)
{
System.out.println("print i=" + B.i); // referred to A.i
}
}
My question here is how B.i is referred to the A.i?
If the static variable i is inherited why java allows to define another variable i in B class also?
A public or protected member of A is visible in all subclasses of A.
If the static variable i is inherited why java allows to define another variable i in B class also?
It's hard to speculate as to why. One possible reason is that this allows one to add members to a base class without breaking any derived classes that already happen to have a member with the same name.
Note that, if you define another i in B, it will shadow A.i, making it difficult to access the latter. I've seen people expecting this to behave polymorphically, but it doesn't (your case is slightly different anyway, since A.i is static).
i here is a static variable.A static variable,in layman terms,means a single copy being accessed by all classes.So,since your class B extends A,B has an access to the static variable of A.
If you define the variable locally,then the local value of the variable hides the parent class value.
there are 2 different things, scope and visibility. you can not redefine a variable in same scope twice (though you can redefine them in nested scopes).
But in case of inheritance, the subclass is out of scope of superclass, but yet has the visibility to that variable because of inheritance. So sub class allows you to define variable i again, though it will hide super class's variable. you wont be able to see its value. (unless used any getter from superclass)
Java allows you to change the specific variable value for the extended class.
This is because, static variables are shared between all objects of the same class.
It is a variable which belongs to the class and not to object(instance).
So, when extending the static variables of the parent class are not actually part of the extended class BUT are accessible (as long as they were not private).
Additionally, this can be used to do things such as:
using different STATIC CONSTANT for extended classes.
A use for this is to identify classes based on a STATIC integer as apposed to utilizing instanceof. This can be further combined with a switch to change behavior based on an objects type.
So, in the most basic example imagine we want to create a variable represent TYPE.
class A
{
public static final int NODE_TYPE = NODE_PERSON;
public static final int NODE_PERSON = 0;
public static final int NODE_CAR = 1;
}
class B extends Class A
{
public static int NODE_TYPE = NODE_CAR;
}
This has been used in many frameworks including Eclipse Abstract Syntax Trees:
http://help.eclipse.org/indigo/index.jsp?topic=%2Forg.eclipse.jdt.doc.isv%2Freference%2Fapi%2Forg%2Feclipse%2Fjdt%2Fcore%2Fdom%2FASTNode.html
You will see a list of STATIC INTEGERS which represent different Node Types.
if we have 2 class Zoo & Moo as follows:
public class zoo {
String superString="super";
private String coolMethod(){
return "Zoo method";
}
}
public class Moo extends zoo{
public void useMyCoolMethod(){
zoo z=new zoo();
System.out.println(superString);//1
System.out.println(z.superString);//2
}
public static void main(String[]args){
new Moo().useMyCoolMethod();
}
}
at 1 & 2 we print the value of the String in the super class through inheritance and access, the question is , what is the benefit of Access although i can do the same thing by inheritance ? knowing that the Access approach isn't allowed if the two classes is in diff packages
By accessing through the object ref you are modifying the referenced object's state, by inheritance you are modifying the object you are currently in ( this reference ). So there is actually no benefit aside from encapsulation at class level and package level through out the access modifiers and that sort of thing, you just use it depending on the behavior you want for you're code, or in this case, how restrictive to modify the state of objects depending on the context.
But aside from that, i'm not sure if there is anything else.
Regarding your example there is no benefit at all in "access" the method, if you really wants to print "super" twice.
But normally OO programs contains more than two classes and the authors tries to modularize the code with defined interfaces (aka public methods or an API). Create modules with inheritance only is very hard and create clumsy code. So objects will need other instances and call there method by "access".
In line 1, you are using inheritance, i.e. you have a class animal and you have method move() which moves the animal using his four leg. But in case of Kangaroo, you want to use most of the feature of animal class but want to change how it moves based on the fact that it jumps and uses it hind leg for movement.
In Line 2, you are using composition, i.e. when you want to create car, you will need different component and they will interact with each other for that car to function. Here you can not inherit from GearBox or Engine but you have to use them as part of Car (or what you are calling access).
In the end its the relationship between Zoo and Moo will decide what method you want to use
Using this access and inheritance is same when you do Not want to modify the content of the inherited memeber..
eg:
public class A {
String s = "Hello";
}
public class B extends A{
String s = "Hi;
System.out.println(s); // Will print the s in class B
System.out.println(new A().s); // Will print the s in class A
}
Now as String s has no modifier, it is considered having Default modifier, that means it can be accessed by classes only with in its own package.
If you use protected access modifier, then you Need to extend the class and then use the inherited members, but you can Not use the protected member by creating an instance of the class that holds it and then use dot operator to access it, this will Not work..
eg :
package com.go;
public class A {
protected String s= "Hi";
}
package com.fo;
public class B extends A {
System.out.println(s); // This will work
A a = new A();
System.out.println(a.s); // This will NOT work
}
The access (default or package-private) would be useful if Moo was in the same package an didn't extend Zoo.
First of all, I think is a good practice to maintain class attributes with private visibility, and access them through getters and setters. In second place, you are not accessing the attribute by inheritance, you are creating an instance of Zoo, and accessing the superString attribute because of it package visibility, you could also access them from another class of the package that don't even extends Zoo class (and that's generally not a good thing) In third place, you don't need to create an instance of the super class to access his public or default attribute, you could simply do:
System.out.println(this.superString)
wich is absolutly the same as (if not local variable or parameter declared with the same name):
System.out.println(superString)
In conclusion, having default or public attributes, let client classes access them (read and write) without the class could do nothing about it, and this could bring side effects for the methods of the class that use those attributes.
Example 2 you have a separate instance of your zoo object, which is a bit weird, but since the method will always return the same thing there isn't much difference. If you changed your method to be based on constructor input or something you could see a difference in the 2.
public class zoo {
public String superString;
public zoo (String _superstring) {
superString = _superstring;
}
}
public class Moo extends zoo{
public void useMyCoolMethod(){
zoo z=new zoo("string1");
System.out.println(superString);//1
System.out.println(z.superString);//2
}
public Moo (String _superstring) {
superString = _superstring;
}
public static void main(String[]args){
new Moo("string2").useMyCoolMethod();
}
}
Will return
string2
string1