Error: "class must implement abstract method X", but it already does - java

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.

Related

'public' class exposes its 'public/*package*/' superType xxxClass [duplicate]

I have the following Java and Kotlin classes:
package nl.friesoft.solaredgenotifier;
class SolarEdgeException extends Exception {
public SolarEdgeException(String s) {
super(s);
}
}
package nl.friesoft.solaredgenotifier
class SiteStorage(context: Context): ISolarEdgeListener {
override fun onError(site: Site?, exception: SolarEdgeException?) {
}
}
And I get this compilation error:
'public' function exposes its 'public/package/' parameter type SolarEdgeException
Both classes are in the same package, so why doesn't this compile?
Classes by default in Kotlin are public, so every member/function is exposed to the outer world. Contrarily, in Java the default visibility, that is omitting a visibility keyword such as public, protected or private, is package-private.
SolarEdgeException is package-private, while its user SiteStorage is entirely public.
That means a user of SiteStorage cannot catch or use your exception at all.
Unfortunately Kotlin doesn't have the concept of package-private, because packages aren't managed the same way as in Java.
The best you can have is internal, which means the definition is visibile to the entire module.
I'd say, in this case, make SolarEdgeException a public class, maintaining the constructor as package-private.
There is a forum thread on the package-private visibility for Kotlin, it's an interesting read. kotlin-to-support-package-protected-visibility

Class must either be declared abstract or implement abstract method: Intellij error?

I made an abstract class
public abstract class AuraSensei {
abstract boolean has();
}
but i'm getting error (see above); need to implement abstract method. thats exactly what I think I did in this code.
public class MariaAura extends AuraSensei {
boolean has() {
return false;
}
}
is this IDE INTELLIJ IDEA fault or am I just being stupid? How can I fix this?
If you're going to be implementing your abstract method in another package, it needs to be protected so it's visible to the subclass. Otherwise, it's as if you're declaring a separate method without overriding the abstract one.
This is one reason why you should always mark method overrides with the #Override annotation.

Why is the protected method not visible?

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!

Having Problems On Organizing Code In Packages

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?

How do I force a polymorphic call to the super method?

I have an init method that is used and overridden through out an extensive heirarchy. Each init call however extends on the work that the previous did. So naturally, I would:
#Override public void init() {
super.init();
}
And naturally this would ensure that everything is called and instantiated. What I'm wondering is: Can I create a way to ensure that the super method was called? If all of the init's are not call, there is a break down in the obejct, so I want to throw an exception or an error if somebody forgets to call super.
TYFT ~Aedon
Rather than trying to do that -- I don't think it's achievable btw! -- how about a different approach:
abstract class Base {
public final void baseFunction() {
...
overridenFunction(); //call the function in your base class
...
}
public abstract void overridenFunction();
}
...
class Child extends Base {
public void overridenFunction() {...};
}
...
Base object = new Child();
object.baseFunction(); //this now calls your base class function and the overridenFunction in the child class!
Would that work for you?
Here's one way to raise an exception if a derived class fails to call up to the superclass:
public class Base {
private boolean called;
public Base() { // doesn't have to be the c'tor; works elsewhere as well
called = false;
init();
if (!called) {
// throw an exception
}
}
protected void init() {
called = true;
// other stuff
}
}
Android actually accomplishes this in the Activity class. I'm not sure how or whether they had to build support into the runtime for it, but I'd check out the open source code for the Activity class implementation. Specifically, in any of the lifecycle methods, you have to call the corresponding super class method before you do anything otherwise it throws SuperNotCalledException.
For instance, in onCreate(), the first thing you have to do is call super.onCreate().
I frequently like to use this solution. It wont throw a runtime error, but it will show a syntax error:
#CallSuper
public void init() {
// do stuff
}
This is a part of Android support annotations.
Make the class at the top of the inheritance tree set a flag on initialization. Then a class in the bottom of the inheritance tree can check for that flag to see if the whole tree has been traversed. I would make documentation that every child of base should include the following init code:
super.init()
if (!_baseIsInitialized) {
// throw exception or do w/e you wish
}
where base uses
_baseIsInitialized = true;
The other way around, forcing your childs to call super.init() is a lot thougher and would most likely include ugly hacks.
I don't know of any way to do this with a method.
However, note that this is exactly how constructors work. Every constructor must, directly or indirectly, call one of its superclass's constructors. This is statically guaranteed.
I note that you are writing an init method. Could you refactor so that your code uses constructors rather than init methods? That would give you this behaviour right out of the gate. Some people (eg me) prefer constructors to init methods anyway, partly for just this reason.
Note that using constructors rather than init methods might not mean using them on the class you're currently looking at - there might be a refactoring which moves the state needing initialisation out into a parallel class hierarchy which can use proper constructors.
Nowadays you can annotate your method with #CallSuper. This will Lint check that any overrides to that method calls super(). Here's an example:
#CallSuper
protected void onAfterAttached(Activity activity) {
if (activity instanceof ActivityMain) {
mainActivity = (ActivityMain) activity;
}
}
In the example above, any methods in descendant classes that override onAfterAttached but do not call super will make Lint raise an error.

Categories

Resources