This is a follow-up to the question: "java access modifiers and overriding". The former generally deals with Java methods however. Why the flexibility with Java fields? We can narrow or widen the visibility with their respect in an inherited class whereas can't with an 'overridden' nor 'hidden' method.
You never override fields to start with - you're always hiding them. Fields aren't polymorphic... in other words, if you write:
Superclass x = new Subclass();
System.out.println(x.field);
and both Superclass and Subclass declare a field called field, it will always use the superclass one anyway, because that's all the compiler can "see".
Personally I try to keep my variables private anyway...
why the flexibility with java fields
You cannot make a field in another class go private by extending it. When you make a new field in a sub class you are just hiding the super class field.
class Base {
protected int x;
}
class Ext extends Base {
private int x; // not the same as Base.x
}
Related
This question already has answers here:
Do subclasses inherit private fields?
(21 answers)
Closed 4 years ago.
I did a little bit of research to know if private instance fields and methods are inherited by a subclass from its superclass.
Actually, I red on different forums contradictory answers but the most convincing one was that, like the java documentation tells, private fields and methods are never inherited BUT that instances of the subclass allocate some memory for the private fields and methods of the superclass.
However, on my most reliable source of documentation, which is the book "java in a nutshell 6th edition" it is said :
This existence of potentially inaccessible members seems to be in conflict with the statement that the members of a class are always accessible within the body of the class. To clear up this confusion, we define “inherited members” to mean those superclass members that are accessible.
Then the correct statement about member accessibility is: “All inherited members
and all members defined in this class are accessible.” An alternative way of saying
this is:
• A class inherits all instance fields and instance methods (but not constructors)
of its superclass.
• The body of a class can always access all the fields and methods it declares
itself. It can also access the accessible fields and members it inherits from its
superclass.
So according to my understanding I came to the conclusion that a subclass inherits ALL fields and methods (including the private ones) from its superclass, but somehow the body of the subclass cannot access the private (and eventually other invisible) members of the superclass.
If I understood well what the book says, isn't that contradictory with what the java documentation tells - that private members are not even inherited -?
Or did I just missed something while reading the book?
Whether a member is inherited or not is primarily relevant to lookup procedures. If e.g. a class B extends A, when the language specification says that private members are not inherited, what this means is that the private members of A only belong to instances of B while viewing them as an A.
The classic example of this looks something like this:
class B extends A {}
class A {
private void m() {}
public static void main(String[] args) {
B b = new B();
b.m(); // error: "cannot find symbol"
A a = b;
a.m(); // fine: m() is a member of A
}
}
There is indeed a method m() which we can call on the instance of B, but the method lookup procedure fails to find it unless we're viewing the B as an A.
With private fields, the in-memory representation of an object will include the private fields of its superclasses, even though we say they are not inherited in JLS terms.
Some further clarifications here are in §8.2:
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.
As well as in §8.3:
A class inherits from its direct superclass and direct superinterfaces all the non-private fields of the superclass and superinterfaces that are both accessible to code in the class and not hidden by a declaration in the class.
A private field of a superclass might be accessible to a subclass - for example, if both classes are members of the same class. Nevertheless, a private field is never inherited by a subclass.
(§8.4.8 also has similar rules for methods.)
These clarify that inheritance does have something to do with accessibility, but there's not a strict 1:1 correspondence. For example, in the following, the field x is accessible to, but not inherited by class B (per §8.3 above):
class Outer {
static class A {
private int x;
}
static class B extends A {
B() {
super.x = 1; // accessible, but must be qualified
}
}
}
One way to put this is that accessibility is a necessary, but not sufficient, condition for inheritance. (In other words, inheritance requires accessibility, but not vice versa.)
Colloquially, it's probably correct to say that private members are inherited, in the sense that 1) a subclass object stores the private variables of its superclasses and 2) the private methods of the superclasses can be invoked on a subclass instance. This is, however, not how the JLS is using the word.
Consider
class A {
private int x;
public A() {
x = 10;
}
public int foo() {
return x * 2;
}
}
public class B extends A {
public B() {
super(); // Calls A's constructor assigning x.
// anything
}
}
int n = B().foo(); // n == 20
It is apparent that an instance of B does carry the member x, with its value. If B did not do so, it could not run the inherited method foo, because that method's implementation in A needs the value of x.
Indeed, B cannot directly access x. But as long as it has any methods that (transitively) depend on that value, via inheritance from A, it must allocate storage for x.
In other words, B is A with something added. Nothing can be removed by inheritance. It can only be made invisible, it it was private. But it's still there, not gone.
If I have a class C which inherits class B and class B inherits class A, then
If I create an object of Class C, is the object of superclasses created?? If yes, how??
How to access the private members of class A??
Does the object of superclass created when object of derived class is created?
No.
The superclass constructor is used to initialize the superclass-defined state of the currebt object, but this does NOT amount to creating an instance of the superclass.
If I have a class C which inherits class B and class B inherits class A, then If I create an object of Class C, is the object of superclass created??
No. See above.
If you create an instance of C, you will have one object whose most-derived type is C. This object will also be an instanceof B, but it may not behave exactly like a regular B due to method overriding in C and other things.
If yes, how??
Moot.
How to access the private members of class A??
You cannot directly access the private members of a superclass from a subclass. That is what the private access modifier means. If you need to access them you need to use them, you either need to create non-private methods in the superclass to do this (e.g. getters and/or setters), or change the members' access.
(An alternative is to use reflection to override the private access modifiers, but you should only use that as a last resort. It is better to fix the superclass code to provide the required access ... or figure out away that the subclass doesn't need access at all.)
yes, the object of super class is created.
You cannot access the private members of your superclass or else they wont be private. you can have protected or public accessor methods in superclass and that could return the value of your private variables. OR, you could use reflection to access the private variables. But that you could use for anything, not only just superclass.
you can not access private variables outside of the class.
to access them,
1. you may make them public or protected but it is not a good idea.
2. you can write getter method for it which is again not a private method,It is good approach.
3. you may use reflection to access it.
provide more information to help you better
It depends on what language you are using. If you are using C++, you may be able to make the sub-class a friend of the super-class and then you could access its public members. If you you use Java, you could use reflection to locate the super object and reflect on that, but it would be more trouble than it would be worth.
I have a superclass Trail that populates an array myList[]. I want a subclass TrailSearch to access myList[] and search it. How can i do this? I know i could simply pass the array to the TrailSearch class as an argument but i'm trying to get to grips with inheritance so i thought i try it the hard way but i need some tips.
PSEUDO CODE
class Main{
new Trail trailObject
new TrailSearch tsearchObject
tsearchObject.methodSearchMyList()
}
class Trail{
constructor Trail(){}
methodPopulateMyList(){
// populate myList[] }
}
class TrailSearch extends Trail{
constructor TrailSearch(){}
methodSearchMyList(){
// search myList[] }
}
that's more or less how i would approach it but what are the rules to make this inheritance idea work?
Inheritance is the wrong way to solve this problem, and this is the wrong problem to use if you are trying to get to grips with inheritance. TrailSearch is not a Trail so shouldn't inherit from it.
A better solution to this problem is the visitor pattern: http://en.wikipedia.org/wiki/Visitor_pattern
Also see
http://msdn.microsoft.com/en-us/library/27db6csx%28v=vs.80%29.aspx for a brief explanation of the "Is A" relationship which implies inheritance.
As long as the myList[] array is not declared private your subclass can access it directly.
Try to define myList[] as a protected variable in class Trail, then you can access the variable from your subclass also
In java, for each field and method, you must declare the visibility. This will determine who can access this field or this method. Visibility is declared with a keyword, which is one of these :
public : The field or method can be accessed from everywhere
private : Only the class where the field / method is declared can access it
protected : Only the class and its subclass can access the field / method.
There's a fourth visibility, called the "package visibility" which takes place when no keyword is specified : the field / method can be accessed within the same package. This visibility isn't used very often.
Here's a little example :
public class A {
public int var2; // this is a public variable
protected int var3; // this is a protected variable
private int var1; // this is a private variable
public void test() { } // this is a public method
protected void test3() { } // this is a protected method
private void test2() { } // this is a private method
}
You can see in my little example, that my class also has a visibility, the exact same rules as for fields and methods are used, only for instantiation instead of accessibility.
In your case, there's two different solution to allow access to your field from the subclass :
declare the field as public, protected or without visibility (ie package visibility)
declare the field as private, and add a setter, getter or others access methods. This is the preferred method and it is called encapsulation.
Since this is probably a homework, I won't provide code to you, it will be a good exercise to write it yourself.
PS: I know that encapsulation is a little more than just what I explained, but dropping the name like that won't hurt the OP ;)
GIVEN:
class A
{
String s = "A";
}
class B extends A
{
String s = "B";
}
public class C
{
public static void main(String[] args){ new C().go();}
void go()
{
A a = new B();
System.out.println(a.s);
}
}
Question:
What are the mechanics behind JVM when this code is run? How come a.s prints back as "A".
Field references are not subject to polymorphism, so at compile time the compiler is referencing A's field because your local variable is of type A.
In other words, the field behavior is like the Java overloading behavior on methods, not the Java overriding behavior.
You probably expect fields to be overridden like method, with dynamic dispatch based on the runtime type of the object.
That's not how Java works. Fields are not overridden, they are hidden. That means an object of class B has two fields named "s", but which of them is accessed depends on the context.
As for why this is so: it wouldn't really make sense to override fields, since there is no useful way to make it work when the types are different, and simply no point when the type is the same (as you can just use the superclass field). Personally, I think it should simply be a compiler error.
This isn't polymorphism (as tagged).
Java has virtual methods, not virtual member variables - i.e. you don't override a property - you hide it.
Although member variables are inherited from a base class, they are not invoked polymorphically (i.e dynamic invocation does not apply to member variables).
So, a.s will refer to the member in the base class and not the derived class.
Having said that, the code is not following OO principles. The members of a class need to be private/protected (not public or default) depending on the business use case and you need to provide public methods to get and set the values of the member.
Let's say we have a class foo which has a private instance variable bar.
Now let us have another class, baz, which extends foo. Can non-static methods in baz access foo's variable bar if there is no accessor method defined in foo?
I'm working in Java, by the way.
No, not according to the java language specification, 3rd edition:
6.6.8 Example: private Fields, Methods, and Constructors
A private
class member or constructor is
accessible only within the body of the
top level class (§7.6) that encloses
the declaration of the member or
constructor. It is not inherited by
subclasses.
But regardless of this language restriction, you can access private fields through reflection:
Field privateStringField =
MyClass.class.getDeclaredField("privateString");
privateStringField.setAccessible(true);
String fieldValue = (String) privateStringField.get(privateObject);
System.out.println("fieldValue = " + fieldValue);
No, for that you should use protected.
For questions like this, where is a table found on the website here: http://java.sun.com/docs/books/tutorial/java/javaOO/accesscontrol.html
Basically you want public or protected variable to be declared in foo since these are the variables that subclasses inherit from their parent and therefore seen in baz.
To use a private variable of a super class in a sub class, an accessor method is required.
Else use the protected modifier instead of private.
Child classes can not access private members (which is the whole point of private access control).
...if there is no accessor method defined in foo?
You need accessors. Besides, take care of inheritance, Should that var really be in parent? Remember IS-A check..
You cannot access private variables in descendent classes. Normally you'd want to use "protected" or "package" (the default) level access for this. However if you want to be really tricky, you can resort to using reflection and AccessibleObject to get at it.
I wouldn't recommend doing that for production code unless you are really in a bind; for testing, etc., it's fine.
The private variable(s) of a class invariably has a scope inside that class. If it has to be shared among the subclasses, it should be declared "protected"
Private members exist(inherited) in instances of child classes .Since, object of Sub class is also an object of Super class, but it is not visible for the sub class
They are accessible indirectly through non-private methods of Super class. These methods can access and manipulate private members
No,bar variable will not be accessible to baz. bar varible should be either protected or public .
Without an accessor method, it's not possible. You have to use a getter setter to access private data members from the superclass.