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?
Related
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.
I have this abstract superclass:
public abstract class MediaListActivity extends Activity {
...
abstract void launchMedia(MediaFile mediaFile);
}
and the concrete subclass:
public class VideoListActivity extends MediaListActivity {
...
void launchMedia(MediaFile mediaFile) {
// TODO: implement launchMedia()
}
}
At the first line of the VideoListActivity subclass, Android Studio gives the error
Class 'VideoListActivity' must either be declared abstract or implement abstract method 'launchMedia(MediaFile)' in 'MediaListActivity'
I can see why it should. But it does! Doesn't it? I've checked that the signature matches; I've tried Option+Return to get the IDE to suggest fixes; nothing works.
Is this just a mistake on Android Studio's part? or am I doing something wrong?
Now it happens that the classes are in different packages: the subclass VideoListActivity is in a "sub-package," foo.bar.baz.video, whereas the superclass MediaListActivity is in package foo.bar.baz.
If I move VideoListActivity up into foo.bar.baz package, the error goes away. But I have several of these concrete subclasses, and I don't want to clutter the top-level package with them: I like them organized into their subpackages. What can I do to make this error go away (assuming it's even necessary)?
The answer is to make sure the implementation of the method launchMedia() is accessible outside its package: i.e. it must be protected or public. I thought I had tried that already, but I might have been looking at the wrong method. Anyway, that makes the error go away.
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'm designing UI Tests for a web application with Selenium in JUnit. I have a base test class with something like this from which I inherit my tests:
public class BaseTest {
protected TestSteps test;
protected Assertions assertion;
// set everything up...
}
and the tests then only look like this:
public class TestX extends BaseTest {
#Test
public testFeature1() {
test.clickSomething().enterSomething(); // method chaining
assertion.assertSomething();
//...
}
}
The problem I'm having: There are different modules in the web app, and Assertions/TestSteps methods that only apply to one module clutter the interface of the Assertions/TestSteps class for the other modules.
Thus I tried to split the Assertions/TestSteps up.
The problem is, the method chaining returns instances of TestSteps. Of course, when I have Module1TestSteps with method doSomethingSpecific() then I would expect test.clickSomething().doSomethingSpecific() to work, but it does not, because clickSomething() would return a TestSteps instance, not a Module1TestSteps instance.
I "solved" this by making an AbstractTestSteps<T extends AbstractTestSteps<T> class (which contains all the base TestSteps methods) protected abstract T getThis();.
I then extend this class like this:
public class BaseTestSteps extends AbstractTestSteps<BaseTestSteps> {
// Constructors
protected BaseTestSteps getThis() {
return this;
}
// that's it, the "base methods" are all inherited from AbstractTestSteps...
}
for the base TestSteps and
public class Module1TestSteps extends AbstractTestSteps<Module1TestSteps> {
// same constructors...
protected Module1TestSteps getThis() {
return this;
}
public Module1TestSteps doSomeThingSpecific() {
// do something
return getThis();
}
}
for my specialized TestSteps. It works for now, but I don't like it because of the following reasons:
All the general methods are in the AbstractTestSteps class, but they are used through an instance of BaseTestSteps
What if I have a submodule of Module1? I can't inherit from Module1TestSteps, only from AbstractTestSteps.
I think it's not trivial to understand the relation of these classes when one of my colleagues tries to add a new TestSteps class.
How can this be made better?
Use the Page Object pattern. That is, create an API for each page so that your tests describe navigating and interacting with pages in a way that describes the user's experience.
It has a few benefits that address your concerns:
It uses composition, not inheritance
It is easy to understand and explain to people maintaining the tests because the tests read like a description of somebody using the application
Given two classes, one subclasses the other, both out of my scope, so I don't have any influence on them, eg.
public class Bla {
}
public class SubBla extends Bla {
}
How can I create a customized subclass of Bla and SubBla without repeating code or limit SubBla's special functionalities?
Edit: So I don't have to:
public class MyBla extends Bla {
public void someOverriddenMethodOfBla()
{
super.someOverriddenMethodOfBla();
// do something custom
}
}
public class MySubBla extends SubBla {
// repeated code: this should do the same as MyBla's customized method
public void someOverriddenMethodOfBla()
{
super.someOverriddenMethodOfBla();
// do the same custom stuff as in MyBla's method
}
}
Edit 2, to clear things up a litte:
Let's say I need the android classes Activity and ListActivity, which is a subclass of Activity. Now I want to add the same customization in the onCreate method to both. How do I acomplish this without repeating code?
Thanks!
If I understand you correctly, you're trying to bypass SubBla's implementation, and invoke Bla's implementation directly from a subclass of SubBla. What you're trying to do is essentially call super.super, which cannot be done in Java
There's a good explanation for this here.
Actually the purpose of inheritance is that you reuse code. In java there only exists public inheritance which means that the accessibility of the methods will remain the same trough inheritance.
If you do MyBla extends Bla then all public methods from Bla will remain still visible in the MyBla class.
Considering your example for Android Activity and ListActivity, subclass ListActivity as CustomListActivity. In CustomListActivity add your version of onCreate(). Now instead of using Activity or ListActivity you use CustomListActivity in your application.