Accessing private members of the superclass [duplicate] - java

This question already has answers here:
Using a private variable in a inherited class - Java
(3 answers)
Closed 6 years ago.
I have two classes, class A and class B which extends class A.
We say that you cannot access private members of the superclass. Let's say that class A has a public method which returns the private member. Now, if we create an instance of class B and call that method, we can actually see that it could access the private member. Why does this happen?

Still you are accessing it's public member (method), no matter what it's internal implementation. You cannot access private members directly, that is what it mean.

Class A has access to the private variable, and class B has access to the getX method. When you call A.getX(), class A passes on the value of x. Think of it like a proxy. You don't have access to that object, but you can route your request through something that does.

By adding the getter method to class A you have changed the contract exposed by A to allow all other classes read-only access that member. Having only a getter does not allow anybody else (including the subclass) to modify the private member, only read it.
There's no particular reason a subclass should be limited in a way that other classes are not.

The private public protected and default modifiers define on which scope a component is accessible, getX() is defined in the scope of class A, for which x is defined private hence it can access x.

Related

Are private fields and methods inherited? [duplicate]

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.

Java accessing private superclass member through protected getter

I know that in Java you can access a private member of a superclass in the subclass as long as the superclass provides a public or protected getter method. I also know however that the subclass does not actually inherit the private member. Considering the following scenario....
Class A {
private var = 2;
protected int getVar(){
return var;
}
}
Class B extends A{
public void printVar(){
System.out.println(getVar());
}
}
Class Main{
public static void main(args []){
B b= new B();
b.printVar();
}
}
I want to understand, since we are creating an instance of the subclass B, what exactly and when is that private member allocated to memory, and what is it's scope? How does it even exist since an instance of A was actually never created? It's not a static variable, or final so is it stack dynamic or implicitly heap dynamic? I thought that when you instantiate a subclass from a super class you inherit the members that aren't private and methods as well and then those get instantiated as part of an object instance of the sub class (unless they're overridden etc), so there is only one object allocated as a heap dynamic variable. But if these private members are not inherited then does the compiler simply provide a stack dynamic reference to them in case the inherited getter method is invoked and only in that case?
Your assumption that the private members of the super-class are not inherited by the sub-class is wrong. All members are inherited. The private members of the sub-class are part of the sub-class instance, but they can't be accessed directly by the code of the sub-class.
Having a protected getter in the super-class that returns the value of the private member gives the sub-class a means to access the value of the private member (though it can't modify it, unless you also have a protected or public setter in the super-class).
I also know however that the subclass does not actually inherit the private member.
Yes it does. An instance of B is an instance of A, and it contains all the same fields. You don't have direct access to the private fields anymore, but they still exist.
How does it even exist since an instance of A was actually never created?
When you create B, a constructor in A is called as well, which makes sure that the B instance is correctly initialized as a valid A. Don't think of a subclass as something different than it's superclass. A B is still an A; it just does more.

I can access a protected field outside of class in java [duplicate]

This question already has answers here:
What is the difference between public, protected, package-private and private in Java?
(30 answers)
Closed 8 years ago.
Ok so I thought the point of having protected fields was so that the variable was accessible by only the subclass and the class having the protected fields. Making objects of either the subclass or the superclass should not grant access to these fields. If I am correct, how come code like this is compiling correctly?
//superclass
public class SuperClass{
protected int x = 5;
}
//main class with main method
public class MainClass{
public static void main(String[] args) {
SuperClass a = new SuperClass();
a.x = 8;
System.out.println(a.a);
}
}
This will print out 8, which means I modified a protected variable outside of the classes which have them...
protected variables and methods are accessible from other classes of the same package as well as subclasses of the current class.
private variables and method are only accessible from within the current class.
If there is no modifier (none of protected, private or public), then by default the variable is accessible from any classes within the same package but not from subclasses.
see here for the official documentation
protected members in Java are also visible to other classes in the package.
Move your main() method to a different package and you'll get an error.
I thought the point of having protected fields was so that the variable was accessible by only the subclass and the class having the protected fields.
You thought wrongly.
Making objects of either the subclass or the superclass should not grant access to these fields.
It does. NB You are now contradicting your own thought here. Your thought includes the subclass, and now you're trying to exclude it.
If I am correct
You aren't.

Public constructor of a private class [duplicate]

This question already has answers here:
Should we declare a public constructor when the class is declared as package private?
(2 answers)
Closed 8 years ago.
I am new to Java. I want to know what it is the use of public constructor in a private class. Private class inside the class can be initialized from the same class then what it is the use to make the constructor of private class to public?
public class MainActivity extends Activity {
private class AcceptThread extends Thread {
public AcceptThread() {
}
}
}
There doesn't seems to be any real use case for public or protected modifiers with private classes. If you have multiple classes in a single file though (but not nested or local), you need non-private constructors to instantiate the private classes.
// X.java
public class X {
private Y y = new Y();
}
class Y {
Y () {
// if this were private, X wouldn't be able to create an instance of Y
}
}
Actually default or protected visibility would be enough to create an instance in this case. All non-private modifiers allow you to create instances from other classes within the same package but practically have the same visibility.
The private class isn't visible to classes outside of the package, so public methods have no use here.
The private class can't be extended by classes outside of the package, so protected has no use either.
Even when using reflections, a public constructor is not accessible by default from other packages and will throw a IllegalAccessException. It checks the class visibility first, then the member visibility.
The default modifier is the most restrictive modifier that allows you to directly call the constructor from other classes, so package-private seems to be the most appropriate visibility for the constructor and also any other non-private methods. This also has the advantage that if you change the class visibility in the future, you don't accidentally expose the constructor or any methods to the public.
You know, I ask myself this question almost each time I make a private inner class, but I always assumed that there could be some (possibly contrived) reason for a public constructor. So #kapep 's answer got me tingling and encouraged to find ways to require a public constructor on a private inner class, but the more I think and experiment with it, the more I think the holes are plugged.
Possible angles, all of which failed me:
Serialisation: When unmarshalling an object whose superclass is not serializable, the superclass needs a no-arg constructor accessible from the subclass. So, protected should always suffice here.
Reflective tools: Code that uses reflection to get the inner class constructor through a returned instance. Fails because the type visibility is checked first, as #kapep pointed out, though it leaves a rather interesting error message:
Exception in thread "main" java.lang.IllegalAccessException: Class A can not access a member of class contrived.B$C with modifiers "public"
Inner class extension shenanigans: Don't try this at home:
package a;
class Outer {
private class Inner {
}
}
package b;
// compile error: Outer.Inner has private access in Outer
class Extender extends a.Outer.Inner {
Extender(a.Outer outer) {
outer.super();
}
}
Seemed promising at first, but I didn't get too far with that one.
In the end, I could not find a way to make a public constructor on a private inner class useful.
Then why is this technically legal despite having no use? Probably because the compiler automagically inserts a no-arg public constructor when no other constructor is provided. Hence the language should not disallow this constructs. More of an artefact than a reason, though.

Does the object of superclass created when object of derived class is created?

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.

Categories

Resources