range of protected method "subclass" means - java

Suppose "class A2" and p"ublic class A" are in the A.java file,
and class B is in a different package than A.java.
This is Class B
public class B {
protected void protectedMethod() {
}
}
And below is A.java File
class A2 extends B {
void tFunc() {
protectedMethod();
}
public class A extends A2 {
void tFunc1() {
protectedMethod(); // OK
A2 a2 = new A2();
a2.protectedMethod(); // Compile Error
why can a2.protectedMethod() not compile??
I understand protected can be called if it is an inheritance relationship,
but why does a compilation error occur when A inherits A2 and A2 inherits B?

Because the language spec says so.
See 6.6.2.1. Access to a protected Member
Let C be the class in which a protected member is declared. Access is permitted only within the body of a subclass S of C.
A subclass S is regarded as being responsible for the implementation of objects of class C. Depending on C's accessibility, S may be declared in the same package as C, or in different package of the same module as C, or in a package of a different module entirely.
In addition, access to an instance field or instance method is permitted based on the form of the qualified name, field access expression (§15.11), method invocation expression (§15.12), or method reference expression (§15.13):
If the access is by (i) a qualified name of the form ExpressionName.Id or TypeName.Id, or (ii) a field access expression of the form Primary.Id, then access to the instance field Id is permitted if and only if the qualifying type is S or a subclass of S.
The qualifying type is the type of the ExpressionName or Primary, or the type denoted by TypeName.
See also:
The True Meaning of private and protected if you find standardese hard to read:
Inside a package, the true meaning of the protected keyword is quite simple. To classes in the same package, protected access looks just like package access. Any class can access any protected member of another class declared in the same package.
When you have subclasses in other packages, however, the true meaning of protected becomes more complex. Take a look at the inheritance hierarchy shown in Figure 5-5. In this hierarchy, class Cup, which is declared in the com.artima.vcafe.dishes package, declares a protected instance method named getSize(). This method is accessible to any subclasses declared anywhere, including those shown declared in package com.artima.other. Any objects whose class descends from Cup--instances of class CoffeeCup, CoffeeMug, EspressoCup, or TeaCup-- can invoke getSize() on themselves. Whether they can invoke getSize() on a reference to another object, however, depends upon where that other object sits in the inheritance hierarchy.
package A;
public class Cup {}
package B;
public class TeaCup extends Cup {}
public class CoffeeCup extends Cup {}
public class CoffeeMug extends CoffeeCup {}
public class EspressoCup extends CoffeeCup {}
If a protected instance variable or instance method is accessible to a class, that class can access the protected member through a reference only if the reference type is the class or one of its subclasses. For example, for code in the CoffeeCup class to invoke getSize() on a reference to another object, that reference must be of type CoffeeCup or one of its subclasses. A CoffeeCup object could therefore invoke getSize() on a CoffeeCup reference, a CoffeeMug reference, or an EspressoCup reference. A CoffeeCup object could not, however, invoke getSize() on a Cup reference or a TeaCup reference.
If class has a protected variable or method that is static, the rules are different. Take as an example the protected static method getCupsInUse() declared in class Cup as shown in Figure 5-5. Any code in a subclass of Cup can access a getCupsInUse() by invoking it on itself or invoking it on a reference of type Cup or any of its subclasses. Code in the EspressoCup class could invoke getCupsInUse() on itself or on a reference of type Cup, CoffeeCup, CoffeeMug, EspressoCup, or TeaCup.

Protected method can be used in context Class A by writing
super.protectedMethod()
Creating new instance of A2 in A class breaches the rule that protected methods cannot be accessed from different packages.

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.

Inheritance Java private members

i have been going through Inheritance in java. My question is if private members are not inherited how come they end up in memory. Is there something going on internally to resolve this issue or they are just hidden/un accesible wihout public member function of the parent class.
here is java doc
"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."
They are in memory, but you don't have access to them.
Example:
class A
{
private int foo;
public int getFoo( ) { return foo; }
...
}
class B extends A
{
...
}
Every instance of class B does, in fact, contain an integer foo under the hood.
But, you cannot access it directly, because it is declared private. You can access it indirectly, via the getFoo method, because that one is public.
Your object has Class reference in it. Your object's Class had parent Class reference in it. That's why private methods are still in memory - they're referenced by parent class.
They are just inaccessible normally, you can access them with e.g. Method.setAccessible(). You can get Method's by reflection on parent Class.

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.

Why exactly does the no-arg constructor of parent class get invoked while creating an instance of child class? [duplicate]

I have a question about inheritance in Java.
I have two classes A and B , and class B, inherits from A:
public class A {
public A() {
System.out.println("Hi!");
}
}
public class B extends A {
public B() {
System.out.println("Bye!");
}
public static void main(String[] args) {
B b = new B();
}
}
When I run program B, the output is:
Hi!
Bye!
Question : why the constructor of class A is invoked, when I create and object of class B ?
I know that B inherits everything from A - all instance or class variables, and all methods, and in this sense an object of B has all characteristics of A plus some other characteristics defined in B. However, I didn't know and didn't imagine that when I create an object of type B, the constructor of A is also invoked.
So, writing this:
B b = new B();
creates Two objects - one of type B, and one of type A.
This is getting interesting,
can somebody explain why exactly this happens?
It doesn't create two objects, only one: B.
When inheriting from another class, you must call super() in your constructor. If you don't, the compiler will insert that call for you as you can plainly see.
The superclass constructors are called because otherwise the object would be left in an uninitialized state, possibly unbeknownst to the developer of the subclass.
Your subclass actually looks like this after the compiler inserts the super call:
public class B extends A {
public B() {
super();
System.out.println("Bye!");
}
}
It doesn't create 2 objects, it only creates one instance of B. The reason the super class constructor is invoked is because, like you said, B has all of the fields of A, and these fields need to be initialized.
Remember inheritance is an "is a" relationship between the base class and the subclass, thus every time you have an instance of a subclass, by definition you will also have an instance of the base class (as part of the instance, not as two separate instances). To initialize the base class properly the constructor is called.
Additionally, think about what would happen if you subclass depended on some internal state of the base class. Wouldn't you want the instance of the base class to be initialized then?
This is done because the constructor is used to initialize the object. Since B is also an A, it calls the constructor for A first, then the constructor for B.
As a side note, you can use super(arg1, etc) to choose which constructor of A is called based on the parameter types you pass... but it must be the first line in the constructor.
The constructor contains all of the initialization for A. You are not creating two objects. You are creating one object, then running the initializer for the superclass to initialize its members, and then running the initializer for the deriving class to initialize its members.
It does not create two objects, it just creates one object b. b is of type B and of type A. A constructor is basically saying here is what you need to do to construct me. So when you are creating a new "B" instance, you are building an object that is both a B() and an A(). Imagine the following scenario:
class Q {
int i;
public Q() {
// set default value
i= 99;
}
}
class Z extends Q {
public Z() {
}
}
If the constructor for Q WAS NOT called, how would i get its default value?
The creation of B does not create an extra A.
But by creating B, you create a kind of A, because B is a A.
Java/C++ call the constructor of A for your implicitly. Why? Language design. But doing so is fine, because the constructor of A might contain some initializations. And as B uses all the features and bugs of A, these features better be initialized properly.
The constructor of a class is very important concept in most OOP
Classes, by providing state and the means to manipulate that state, allow the easier maintenance of invariants. The constructors role is to get the class into a state that conforms to those invariants (or throws thus forbidding usage of an invliad object).
this is somewhat looser than intended in many languages since the constructor is allowed to pass its own 'this' reference elsewhere but this is at least under the control of the class (as such it can know that it is in a sufficiently stable and valid state for it to be accessible to the rest of the world)
Inheritance makes this complex since B is-a A in a very real sense and thus can invoke any of the methods provided by A. The parts of B that are A should therefore get their chance to initialize themselves before B gets a look in, thus the constructor for A is called before the real work of the B constructor begins.
If A intializes members in it's constructor and you forget to call super in your derived class then the members of A could be in a bad state. Java is trying to stop you from shooting yourself in the foot.
Only one object is created, both contractors are running on the same object.
The reason is simple, as you know B has all the variables and methods of A, so if some variable of A needs initializing so methods of A can work someone has to initialize it - and that someone is A's constructor.
for example:
public class A {
public A() {
x = 1;
}
private int x;
public int getX() {
return x;
}
}
public class B extends A {
public B() {
}
public static void main(String[] args) {
B b = new B();
System.out.println(b.getX()); // should print 1
}
}
When new object is create(B), inside B A object is created(because of extends keywords) . In B class JVM search B class constructor, but due to extends keywords it goes to super class constructor. inside A class x value is initialized. But x is private so that we can access outside class throw getXxx() method and get the result.
When sub class object is created then internally it was not created for super class object.But the memory should be allocated for super class members.
In java when you create an object of child class the constructor of parent class is always called because Object class is the parent of every super class and when you call the constructor of Object class then only your object is created and java does not support multiple inheritance in case of class so if you extends any other class then the relationship between you child class and the Object class is through the Parent class so to call the constructor of the Object class the constructor of Parent class must be called.
Every superclass has a constructor and each constructor up the hierarchy runs at the time an object of a subclass is created.
if super class object is not created then how sub class is accessing super class non static methods and variables.
I studied that non-static methods and variables can be accessed only through objects..

How are java.lang.Object's protected methods protected from subclasses?

The keyword protected grants access to classes in the same package and subclasses (http://java.sun.com/docs/books/tutorial/java/javaOO/accesscontrol.html).
Now, every class has java.lang.Object as superclass (http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Object.html).
Hence I conclude that every class may access java.lang.Object's methods even if they are protected.
Take a look at the following example:
public class Testclass {
public Object getOne() throws CloneNotSupportedException {
return this.clone();
}
public Object getTwo() throws CloneNotSupportedException {
return ((Object) this).clone();
}
}
While getOne() compiles fine, getTwo() gives
Testclass.java:6: clone() has protected access in java.lang.Object
return ((Object) this).clone();
I neither understand why getTwo() doesn't compile nor what's the difference (regarding the access of java.lang.Objects members) with getOne().
You can only access protected members of a type in a different package if the compile-time type of the expression you're referencing it through is either your own class or a subclass. (Where "your" class is the class containing the code.) Your own class has to be a subclass of the type which originally declares the method, too.
Here's an example; assume that Base is in a different package to all the other classes:
package first;
public class Base
{
protected void Foo() {}
}
// Yes, each class is really in its own file normally - but treat
// all the classes below as being in package "second"
package second;
public class Child extends Base
{
public void OtherMethod(Object x)
{
((Base) x).Foo(); // Invalid: Base is not Child or subclass
((Child) x).Foo(); // Valid: Child is Child
((GrandChild) x).Foo(); // Valid: GrandChild is subclass of Child
((OtherChild) x).Foo(); // Invalid: OtherChild is not Child or subclass
}
}
public class GrandChild extends Child {}
public class OtherChild extends Base {}
In other words, it's letting you have access to the protected members of "objects which are a like you".
Details are in section 6.6.2 of the Java Language Specification:
A protected member or constructor of
an object may be accessed from outside
the package in which it is declared
only by code that is responsible for
the implementation of that object.
6.6.2.1 Access to a protected Member
Let C be the class in which a
protected member m is declared. Access
is permitted only within the body of a
subclass S of C. In addition, if Id
denotes an instance field or instance
method, then: If the access is by a
qualified name Q.Id, where Q is an
ExpressionName, then the access is
permitted if and only if the type of
the expression Q is S or a subclass of
S. If the access is by a field access
expression E.Id, where E is a Primary
expression, or by a method invocation
expression E.Id(. . .), where E is a
Primary expression, then the access is
permitted if and only if the type of E
is S or a subclass of S.
When you said "((Object) this).clone()", you accessed your own object via its superclass Object. You performed a widening conversion to an Object. The code then attempts to call clone on Object.
But, as you've noted, clone is a protected method, meaning that only if your object was in the same package of java.lang would it be able to access the OBJECT's clone method.
When you say this.clone, your class extended Object and thus had access to override or use clone directly through the protected class modifier because of inheritance. But that doesn't change the Object implementation.
By saying ((Object) yourObject), you get something that is only accessible through the Object class. Only public methods of the Object class are accessible ouside of the package java.lang, so you get the compile-time exception, because the compiler knows this.
By saying this.clone(), you are invoking your object's clone method that it got through inheriting through Object, and is now able to be invoked because it becomes a part of your custom subclass.
The difference is how you are accessing Object.clone(). clone is only accessible when accessed via a sub class or class in the same package. In the getOne() example you are claling this.clone(). This clearly satisfies access from within a sub class.
In getTwo() though you are acessing Object.clone() and not TestClass.clone(). In order for this to work you must have package level access to Object which you don't and hence the error.

Categories

Resources