I have an question which comes under multilevel inheritance in Java. All Three Classes are in Same package
I have class A :
public class A {
protected int x;
}
public class B extends A {
public void doSomething {
// x is visible.agreed, as it is a direct subclass of A
}
}
public class C extends B {
public void doSomething {
// x is still visible, how come? I mean it is at the 2nd level
// I am confused why?
}
}
does it like have any significance? or it is behavior which we have to take it by default?
variable/methods marked with protected modifier are visible to all the classes in the same pacakage and only to subclasses in different packages.
below are the example cases.
package a;
class A{
protected int x;
}
class B extends A{
//x can be accessed from this class
}
class C extends B {
//x can be accessed from this class
}
class D{
//x can be accesed this class but you will have to create A's instance
}
package B
class One {
//cannot access x from this class
}
class Two extends A {
//can access x from this class
}
The access level modifiers in Java are:
public - visible to all code
protected - visible to all code in the same package and to subclasses regardless of package
nothing (default) - visible to all code in the same package
private - visible only to code in the same class (including nested classes)
See, for instance, the Java tutorial Controlling Access to Members of a Class or (for lots of technical details) section 6.6 of the Java Language Specification.
Definition of the keyword
Protected
The protected modifier specifies that the member can only be accessed
within its own package (as with package-private) and, in addition, by
a subclass of its class in another package.
I suggest you read this.
The Java protected keyword works its way down to all subclasses (and members of the package). If there was a protected member in Object, any object could access it. By contrast, private is only visible to the local class (and inner classes), and public is accessible by all.
Have a look at this glossary, which shows in-depth how protected members and methods are inherited, and the Java documentation on inheritance.
You cannot restrict access to members in subclasses. This rule applies to methods (you can't override public method and make it private) but you can see analogy here. If the field is protected, it will be protected in every subclass, no matter how deep. Of course you can't override fields in Java, but just to give you an overview.
Please refer this: http://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html
The protected modifier specifies that the member can only be accessed within its own package (as with package-private) and, in addition, by a subclass of its class in another package.
So if your class C shares the package with A and B, its accessible.
Inheritance is transitive: if class B inherits from class A;
and class C inherits from class B; then C is also a
subclass / child class / descendant of class A.
Related
package pack1;
class A{
protected void m1(){
System.out.println("protected modifier");
}
}
package pack2;
class B extends A{
public static void main(string[]args){
B b = new B();//Valid
b.m1();
A a = new B();//Invalid
a.m2();
A a1 = new A();//InValid
a1.m1();
}
}
Why while accessing protected members outside package we need to have child class reference only.?
Why we cant use parent reference to access protected members (Here A a = new B())?
I have gone through blogs and many stack overflow answers but didn't find any answer for WHY?.
so can anyone help me knowing the answer for WHY?
You are not allowed to access A because you are still outside of a subclass or package. The main method is static, thus unbound from instances of the B class. In order to access A you need to be inside the B class, so in a non-static context like
public class B extends A {
public void foo() {
m1(); // Valid call since inside subclass
}
}
I think you have misunderstood what static means.
The details of protected are described in the Java Language Specification. Extract from JLS§6.6.2:
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.
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.
The limitation even goes beyond your example. The key is "responsible for the implementation". Compare that to the following example:
package a;
public class Point {
protected int x;
protected int y;
}
package b;
import a.Point;
public class Point3D extends Point {
public void delta(Point other) {
other.x += this.x; // Compile-time error: Cannot access other.x
other.y += this.y; // Compile-time error: Cannot access other.y
}
}
Though the class Point3D is a subclass of Point, it is not responsible for the implementation of the other object. Thus, it is not allowed to access its protected members.
Same for
public class B extends A {
public void foo() {
A other = new A();
other.m1(); // Compile-time error
}
}
since the current instance to which the foo() method call belongs to is not responsible for the implementation of other. Thus, access is not permitted.
The concept of inheritance/polymorphism makes the inherited public and protected methods and variables of the parent class - members of the child class and is therefore accessible to the objects of the child class. protected access requires two rules-
can only be accessed by classes that are within the same package
can be accessed via inheritance.
A a = new B();
a.m1(); //doesn't compile
This is an instance of the B class but as far as it is a reference of A, it is an A object. That is why the object "a" only has access to members that are common to A and B. i.e object "a" as a reference of class A has access only to the inherited methods of class B. It does not have access to any method or class variable of B that is absent in A even though it is an instance of class B. You have to explicitly cast it to a B to give it access to unique methods & variables of class B. So, bearing this in mind, as far as Java is concerned, object "a" is a class A object that is in another package. Therefore even though the method a.m1 was inherited, "a" does not have access to it because it is an A object in another package. a.m1 will compile in pack1.
Contrast that with this code
B b = new B();
b.m1() //compiles
b is an object of B and therefore rule 2 of the protected access applies. Since m1 is an inherited protected method of the object B, it has full access to it.
Consider the following snippet.
package breakoop;
public class BreakOOP {
public static class A{
private int a;
}
public static class B extends A{
public int f(){
return super.a;
}
}
public static void main(String[] args) {
B b = new B();
System.out.println(b.f());
}
}
The example only compiles if A and B are encapsulated within the BreakOOP class.
This seems to go against some of the fundamental concepts of OOP. Can someone explain why this compiles? What is the reasoning behind it?
Check this: https://docs.oracle.com/javase/tutorial/java/javaOO/nested.html. It says it increases encapsulation by allowing the static class to access private members of the top level class (sometimes you may need to do that). And a is private member of class A, which is in the scope of BreakOOP, which in turn makes it accessible inside class B.
The Java Language Specification states:
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.
Since classes A and B are defined within the body of BreakOOP that rule applies and B can see private members of A.
As for the OOP concepts: since A and B are static inner classes they don't have the special life-cycle relation with BreakOOP that true inner classes have (i.e. you don't need an instance of BreakOOP to create a new instance of A or B but they still have a somewhat special relation in that they have access to private members. If they should not have that kind of relationship then they shouldn't be inner classes but true top level classes.
I am not sure why in a context like the following
class Parent {
private void method1() {
System.out.println("Parent's method1()");
}
public void method2() {
System.out.println("Parent's method2()");
}
}
public class Child extends Parent {
public void method1() {
System.out.println("Child's method1()");
}
public static void main(String args[]) {
Parent p = new Child();
p.method2();
}
}
Parent may be package private, but not protected.
Specifically the error generated is
modifier protected not allowed here
Which would seem to indicate that it is an issue of access privilege - but I am suspicious that this may be a red herring. Private modifier also generates an error (naturally).
In Java, Top level classes can have only package private and public modifiers.
Making a class private doesn't make any sense. If no one use that class for any reason, then why we need that class?
protected access modifier means, only visible within the enclosing class and any subclasses, and also anywhere in the enclosing class's package. No body knows which classes going to be subclass of a protected class. So, it also doesn't make sense
But both private and protected can be (and frequently are) applied to nested classes and interfaces, just never top-level classes and interfaces
You cannot use the protected access modifier for top level classes.
according to the spec $8.1.1
The access modifier public (§6.6) pertains only to top level classes (§7.6) and to member classes (§8.5), not to local classes (§14.3) or anonymous classes (§15.9.5).
The access modifiers protected and private (§6.6) pertain only to
member classes within a directly enclosing class or enum declaration
(§8.5).
Are the fields or the methods of class with default access inhereted to the subclasses when they both exist in the same package, or should they be still declared as protected?
Example:
package mypackage;
class A{
int x = 3;
}
class B extends A{
}
Has the B class also a field x?
See description:
Hope it will sort things out
[EDIT]
From table for default modifier like in your case:
Accessed only from within the package in witch they are declared.
Means if class A and B stay under the same package, you can for example print out the x:
class B extends A{
public static void main(String[] args) {
new B().init();
}
private void init() {
System.out.println(x);
}
}
However, if we put class B to different package, an error will be thrown: The type mypackage.A is not visible. So here you must set public modifier.
With default access the properties are only visible to classes in same package.
But with protected access they are accessible to all classes in same package and subclasses (regardless of package). Choose what is relevant in your context.
Has the B class also a field x?
Yes B inherits the property x of A
In the case of default sub class [if in the same package] has the privilege to use the methods/data members.
class B extends Class A{
System.out.println(new B().x); //will surely work in your case(Example shown).
}
Yes you can access the public , default(If classes are in same package) and protected data members using inheritance:
public class A {
int a;
}
public class B extends A {
B() {
a = 5;
}
Are fields only inherited "one level up"?
By that I mean that if I have a Superclass to a Class, which then has a Subclass, and the Superclass has a field, the Class will inherit it and the Subclass won't. Is this correct?
And if it is, is there a way to make the Subclass automatically inherit the field from the Superclass given that, as I understand it, there's no way to inherit from two classes at once?
Thank you to anyone who takes the time to answer. I realize my question may be impractical and in reality you'd probably just override the field or something, but I'm not trying to do anything specific, just trying to learn how Java works. Thank you.
Here's my code:
public class SuperClass {
protected int entero;
protected void method(){
entero=1;
}
public class SubClass extends Class {
public SubClass(){}
}
public class Class extends SuperClass {
public Class(){}
}
public static void main(String[] args){
Class object= new Class();
SubClass subobject= new SubClass();
/*This is where I get an error, why?*/
subobject.entero=2;
/*This one is fine*/
object.entero=2;
object.method();
System.out.println(object.entero);
}
Any class B than extends a class A, will inherit A's fields. If a class C extends B, C will inherit all non-private instance fields and methods from A and B, ie transitivity holds.
If a field is private, then one cannot directly change it from a subclass; however, you can get around this by using setter/getter methods.
If a field is protected, then a subclass has direct access to it.
EDIT 1:
In a comment you say that the field is protected, but you still can't access it from a subclass. The only thing I can think of is that you have a situation like this:
class A
{
protected int x;
}
class B extends A
{
private int x;
}
class C extends B
{
private int z = x;
}
This would NOT work because by declaring x again in B, you are hiding the x field from A. So, now C sees x as B's private variable x, which you do not have access to.
EDIT 2:
I'm not going to remove the above edit, because it's informative, but now that you posted your code, it's because your SubClass does not actually extend anything (this was later fixed in an edit).
Inheritance in Java is transitive.
If your classes are Superclass < Class < Subclass, then Subclass inherits all the non-private instance fields and methods provided by Superclass not overridden or hidden by Class or Subclass.
One level of inheritance is specified by the Java Language Specification, section 8.4.8: Inheritance, Overriding and Hiding:
A class C inherits from its direct superclass and direct superinterfaces all abstract
and non-abstract methods of the superclass and superinterfaces that are public,
protected, or declared with default access in the same package as C, and are neither
overridden (§8.4.8.1) nor hidden (§8.4.8.2) by a declaration in the class.
If you have classes that are:
public class SuperClass {
public void methodName() {}
//SuperClass's stuff
}
public class MidClass extends SuperClass {
//MidClass's stuff
}
public class SubClass extends MidClass {
//SubClass's Stuff
}
Then it is perfectly valid to have in your main method:
SubClass sc = new SubClass();
sc.methodName();