Look, PlanetShape extends Shape!
And yet it says isOverlapMethodLevel have protected access in Shape!
Did I just discovered a bug in android studio? Or is it something else?
The packages differ in your class hierarachy - specifically your PlanetShape class is in a different package to the classes it extends.
Directly from Java documentation: (emphasis mine)
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.
Clearly the "by a subclass of its class in another package" seems to be the cause of some confusion and I agree that the wording is rather ambiguous.
Basically, what they're trying to say is you can do this:
public class PlanetShape extends Shape {
aMethod() {
// call the protected method declared in the Super class (ok)
doProtectedMethodOfShape();
}
}
But not this:
public class PlanetShape extends Shape {
aMethod() {
Shape s = new Shape();
s.doProtectedMethodOfShape(); // error here
}
}
In the second example, you get an error because you're not accessing a protected method via inheritance, you're just trying to access a protected member function from an instance in another package.
Related
Java experts, I would sincerely appreciate any insights!
I have an abstract class in a package with a protected method. I also have a subclass of this class in the same package. Now, when I try to instantiate the subclass from a class outside the package, and invoke the protected method on the subclass' instance, Eclipse is complaining the protected method is not visible.
I thought, protected methods will be visible to all children - in or out of the package - as long as the class visibility does not restrict it - in this case, both the parent and the child class are public. What am I missing? Thanks in advance!
package X;
public abstract class Transformation {
protected OutputSet genOutputSet (List list) {
..
}
}
package X;
public class LookupTransformation extends Transformation {
}
package Y;
import X.*;
public class Test {
public static void main(String[] args) {
List<field> fld_list = new ArrayList();
..
LookupTransformation lkpCDC = new LookupTransformation();
OutputSet o = lkpCDC.genOutputSet(fld_list); // Eclipse errors out here saying genOutputSet from the Type Transformation is not visible. WWWWWWWWHHHHHAAAATTTTTT????
}
}
protected access means genOutputSet can be called by classes inheriting from the class where it's declared or by classes belonging to the same package. This means you can call it from within LookupTransformation.
However, you are trying to call it from an unrelated class - Test - located in a different package, which requires public access.
See additional explanation here.
Your code is not in a subclass (you're in Test), and your code is not in the
same package (you're in Y). So the method is not visible. That's normal.
protected means you may call the method in any derived class. However, Test isn't derived from Transformation. genOutputSet is only visible inside Transformation and LookupTransformation. This doesn't tell anything about the visibility of methods when they are called on an object of the derived class.
The best possible answer I could give would be in the form of this picture that I used to learn it myself:
Protected methods work on subclasses(inherited classes in your case) that are in other packages aswell. You are however calling it from a different class(not subclass). Hope this helps!
I've got some doubts regarding protected identifier. In the first chapter of Sun Certified Java Programmer Study Guide by K.Sierra I found the following information:
"Once the subclass-outside-the-package inherits the protected member, that member (as inherited by the subclass) becomes private to any code outside the subclass, with the exception of subclasses of the subclass."
I provided sample code which reflects the above statement and it is absolutely clear to me.
// Parent class
package package1;
import package2.Child;
public class Parent {
protected int i = 5;
}
// Child class
package package2;
import package1.Parent;
public class Child extends Parent {
// variable 'i' inherited
}
package package2;
public class Neighbour {
public void protectedTesting(){
Child child = new Child();
System.out.println(child.i); // no access
}
}
I've started experimenting and made a small change - moved Neighbour to package1. And there is an access to "i" variable which is a little bit surprising for me as it is not in accordance to statement "becomes private to any code outside the subclass"
Neighbour class after change:
package package1;
import package2.Child;
public class Neighbour {
public void protectedTesting(){
Child child = new Child();
System.out.println(child.i); // access!
}
}
Please clarify it to me. Thanks.
In short, protected is package-private as well as visible to subclasses. Even the JLS is vague on this (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.
It specifies that outside the package, only subclasses can access protected members. This implies that you can also access the variable within the package. It's poor wording, but true nonetheless that protected members have package-level visibility as well as subclass-level visibility.
See also:
This related question
The Java Trail for access control
And there is an access to "i" variable which is a little bit surprising for me as it is not in accordance to statement "becomes private to any code outside the subclass"
--> But you moved class Neighbour in package package1 which is true according to "Protected members can be accessed by classes in same package"
"Once the subclass-outside-the-package inherits the protected member, that member (as inherited by the subclass) becomes private to any code outside the subclass, with the exception of subclasses of the subclass."
--> Inside package it is still protected and not private for all classes within the package.
The truth is not in "Sun Certified Java Programmer Study Guide" but in the Java Language Specification
6.6.2. Details on protected Access
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.
protected visibility includes package level visibility.
Inheritance allows you to treat your Child object as an instance of Parent.
As the member i of Parent is declared in the same package, it is accessible from Neighbour.
package package1;
import package2.Child;
public class Neighbour {
public void protectedTesting() {
Parent neighboured = new Child();
System.out.println(neighboured.i); // access
}
}
On my Android project I have the main Activity called TestFIO, which is in the package org.testing.file.io.main, and I tried to keep it clear and sent all the functions I had to a new class called FileManipulator, which is located at org.testing.file.io.main.manipulator. Here is how the FileManipulator class looks like:
package org.testing.file.io.main.manipulator;
// imports here
public class FileManipulator extends TestFIO {
public String readFileFromCard(String location) {
// some code here
}
// more functions here
}
And here is an example of TestFIO:
// header with package and imports
import org.testing.file.io.main.manipulator.FileManipulator;
public class TestFIO extends ListActivity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final String[] fileString = readFileFromCard(Environment.getExternalStorageDirectory() + "test.txt");
}
}
The problem is that Eclipse is underlining readFileFromCard and showing the following error:
What am I doing wrong or how is the correct way to organize my code in packages?
PS: Sorry if this is a dumb question, I'm coming from iOS development.
The compile problem is because you're trying to call a method defined in a subclass from the superclass. Inheritance doesn't work that way; subclasses inherit all public and protected methods from the superclass, but superclasses don't know anything about the methods of their subclasses.
Additionally, it doesn't seem reasonable to have FileManipulator extend your Activity class. Does FileManipulator pass the "is-a" test, in other words, is it a kind of Activity? It seems more like it's a "helper" class that the Activity will use to do its work. In that case, FileManipulator should not extend TestFIO but rather be stand-alone, created by TestFIO.
I see TestFIO is parent class, FileManipulator is child class according to your code.
Then you can't call child class' method, you need a instance of FileManipulator.
Am I wrong?
Iam preparing for SCJP , also i came to know that protected members scope is within the package as well as in other package with some conditions like possible only with inheritance.
For example :
i have three classes as Parentclass Childclass Friendclass
package x.parent;
class Parentclass{
protected int x=10;
...............
}
package x.child;
class Childlass extends Parentclass{
super.x=20;
...............
}
package x.child;
import x.parent.Parentclass;
class Friendclass{
Parentclass pc = new Parentclass();
pc.x=30;
...............
}
Whats the reason behind that, in Friendclass the member x will not accept to assign a value to that, behaves as private member not in case of Childclass.
There are four access modifiers
private - just this class
no modifier - just this class or this package (NOT subclass)
protected - just this class, this package, or subclass
public - everyone and their cousin
Since it uses the default modifier, it has access if one of the following is true:
Is part of the class itself (Nope!)
Is part of the package of the class itself (Nope!)
So it fails the criteria, and so you don't get access.
You can't even access Parentclass.x in Childclass because x has default visibility (not protected). See http://download.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html
edit:
x.child.Friendclass is not in the same package as x.parent.Parentclass.
x.child.Friendclass does not inherit from x.parent.Parentclass.
as TotalFrickinRockstarFromMars's summary states and the Java access control docs also state, this means that Friendclass is not allowed to access the field x.
In java, there's three levels of access:
Public - Open to the world
Private - Open only to the class
Protected - Open only to the class and its subclasses (inheritance).
So why does the java compiler allow this to happen?
TestBlah.java:
public class TestBlah {
public static void main(String[] args) {
Blah a = new Blah("Blah");
Bloo b = new Bloo("Bloo");
System.out.println(a.getMessage());
System.out.println(b.getMessage()); //Works
System.out.println(a.testing);
System.out.println(b.testing); //Works
}
}
Blah.java:
public class Blah {
protected String message;
public Blah(String msg) {
this.message = msg;
}
protected String getMessage(){
return(this.message);
}
}
Bloo.java:
public class Bloo extends Blah {
public Bloo(String testing) {
super(testing);
}
}
Actually it should be:
Open only to the classes on the same package the class and its subclasses (inheritance)
That's why
Because protected means subclass or other classes in the same package.
And there's actually a fourth "default" level of access, when the modifier is omitted, which provides access to other classes in the same package.
So protected is between default and public access.
To be more specific, you're expecting protected to work as it does in C++.
However, in Java, it has a different meaning. In Java, a protected method is available to the class (obviously), all the other classes in the same package and any subclasses of this class. Classes in other packages will not have access unless they subclass this original class.
See this similar question for more specific information on inheritance markers.
Personally, I almost never use protected. I develop applications rather than frameworks so I'm much more likely to define public methods, private data and, quite often, mark my whole class as final.
There are actually four levels of access: "public", "protected", "private" & default also known as package private or package protected. Default limits accessibility to the package. Default is quite useful and I use it frequently.
You're able to call b.getMessage() because b is of type Bloo, which extends Blah, and getMessage() is protected. Protected, as you mentioned, allows subclasses to access the method.
You've got the following errors, though:
Calling super() with no arguments in the Bloo constructor is an error. The compiler can't find the no-parameter Blah constructor because you defined one with a String parameter.
Calling new Blah() in TestBlah main method is an error for the same reason as above.
Referring to a.testing and b.testing is an error because you didn't define the variable testing for any class.