Overriding in Java/Android (class -> anonymous class) doesn't work.. why? - java

I've a simple inheritance problem.. but I can't solve it.
This is the basic class:
public abstract class RpcOkCallback extends RpcTupleCallback
{
// [...] constructor [...]
public boolean callback(int responseCode, final String module, boolean flag){
if (flag){
return onResponse(responseCode, module);
} else {
return onError(responseCode, module);
}
return false;
}
protected abstract boolean onResponse(int responseCode, String module);
protected boolean onError(int responseCode, String module){
return true;
}
}
And this is an anonymous class that redefine the base class:
new RpcOkCallback("color_seek_ir", "set_flash_ir"){
#Override
protected boolean onResponse(int responseCode, String module) {
if (seekBar != null) seekBar.setEnabled(true);
return true;
}
#Override
protected boolean onError(int responseCode, String module) {
if (seekBar != null) seekBar.setEnabled(true);
return true;
}
}
The question is.. why when the onResponse method is called it calls correctly the overridden method while when it calls the onError method, it calls the base case (the "return true" method)? I've tried to declare abstract the "return error" method too and it works... but I don't want to declare in every anonym class a basic method like that.
Any idea? Thanks :)

I found the problem. It actually works correctly (the overriding part), but the callback was already handled by another "onError" method (not overridden) and because of the "return true" the event was canceled before reaching the final destination :(
Adding the abstract and defining all the methods did the job, so thanks corsair (if you want to add your answer or what I will mark as solved the question by you :) ).

Related

Get correct return value with abstract method inside function

I would like to check the result of an AsyncTask inside a method.
private boolean isRequestSuccessfull(){
boolean test = false;
new HttpRequest() {
#Override
public void onResponseReceived(JSONObject result) {
if (result.optBoolean("success")){
return true;
} else {
return false;
}
}
}.get(getBaseContext(), "myUrl");
return test;
}
isRequestSuccessfull check if the result of the httpRequest is successfull.
HttpRequest is an AsyncTask who call the server and onResponseReceived is the abstract method who allow me to get the result of the request.
This code isn't working because I can't have a return boolean inside onResponseReceived.
I can't assigne the value test inside the onResonseReceived and return it, because the return will be executed before the assignement.
How can I solve this ?
Instead of returning a boolean from your method make it void and let your anonymous HttpRequest do the method call when the response has been received e.g.
new HttpRequest() {
#Override
public void onResponseReceived(JSONObject result) {
if (result.optBoolean("success")) {
callMethodWithBoolean(true);
} else {
callMethodWithBoolean(false);
}
}
}.get(getBaseContext(), "myUrl");

Handling conditional statements while designing a logger like class?

How do you handle the conditional statements while designing a class like log4j?
Taking log4j example, a class can have different levels(Info, Warning, Error, others...). Now to print for the different levels you would need different methods for each level. So there could be a basic design as follows:
public class CustomLogger {
enum Level{
INFO, WARNING, ERROR;
}
private Level level;
public CustomLogger(Level level) {
this.level = level;
}
public void info(String s){
if(level == Level.INFO || level == Level.WARNING || level == Level.ERROR){
System.out.println(s);
}
}
public void warning(String s){
if(level == Level.WARNING || level == Level.ERROR){
System.out.println(s);
}
}
public void error(String s){
if(level == Level.ERROR){
System.out.println(s);
}
}
}
The problem with this design I guess is that it has way too many if conditions and in case I need to add a new state I would have to modify all the if cases. So what I think could be a better design is as follows:
There is a State super class which is extended by class Info, class Warning and class Error. The State class has methods printInfo(), printWarning() and printError(). All the subclasses implement these methods and leave blank the once they need. As an example class Warning would look like:
class Warning extends State{
public void printInfo(String s){
//don't print
}
public void printWarning(String s){
System.out.println(s);
}
public void printError(String s){
System.out.println(s);
}
}
Now the CustomLogger will have an association with State which will be injected to it at some moment and all the methods in CustomLogger will call methods of State class implementation. Something like:
public class CustomLogger {
private State state;
public CustomLogger(State state) {
this.state = state;
}
public void info(String s){
state.printInfo(s);
}
public void warning(String s){
state.printWarning(s);
}
public void error(String s){
state.printError(s);
}
}
Even though this eliminates the conditional cases, but it induces a dependency of the methods call. If I add a new State then that states printState() method would have to added to every subclass which I guess is not a good practice. What else can be done in such cases?
The best answer, in this case, depends on how your system's requirements could change in the future. Even if you follow the Open/close principle you cannot prevent every possible scenario which violates this principle, so you try to cover in your design those that you think are more likely to appear.
Anyhow, a good solution for your case study would be similar to the one implemented by Java Logger. Where a numeric values is associated to the Logger level (every possible Level has its value) that allow you to check if the current Logger should write anything to the log with a single if. Besides it is very easy to extend its behaviour without modifying the current code.
For example when you call Logger#info(String):
public void info(String msg) {
log(Level.INFO, msg);
}
Method log is as follows:
public void log(Level level, String msg) {
if (!isLoggable(level)) {
return;
}
// do any logging you want here
}
And finally the key isLoggable:
public boolean isLoggable(Level level) {
if (level.intValue() < levelValue || levelValue == offValue) {
return false;
}
return true;
}
Where levelValue is "the current effective level value" of the Logger.

Track Method Dependencies Via ASM

I'm trying to track method dependencies via ASM. For example, lets say I have class like this:
class Test{
public void methodToRun(){
Depedencies.startTracking();
//method calls here
Depedencies.stopTracking();
}
}
and methodToRun is called. Since I have Depedencies.startTracking() I need to start printing out all method call details still I see Depedencies.stopTracking().
I tried to do this via ASM with the below code:
public class ClassPrinter extends ClassVisitor {
#Override
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
MethodVisitor mv = cv.visitMethod(access, name, desc, signature, exceptions);
MethodAdapter adapter = new MethodAdapter(mv);
return mv == null ? null : adapter;
}
}
and then the adapter looks like this:
class MethodAdapter extends MethodVisitor implements Opcodes {
public MethodAdapter(final MethodVisitor mv) {
super(ASM5, mv);
}
#Override
public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) {
if(name.contains("startTracking")){
System.out.println("Started tracking")
TrackerState.startTrack();
}else if(name.contains("stopTracking")) {
System.out.println("End of tracking")
TrackerState.stopTrack();
}
if(TrackerState.status())
{
//print the details.
}
mv.visitMethodInsn(opcode,owner,name,desc,itf);
}
}
class TrackerState {
private boolean static track = false;
public static void startTrack(){
track = true;
}
public static void stopTrack() {
track = false;
}
public static boolean status() {
return track
}
}
The above ASM code works only for one level method call tracking. Meaning, it doesn't track if a method calls another method ( which I supposed to be track ), below code explains the problem:
class Test {
public void methodRunning()
{
Depedencies.startTracking();
method1() //tracked , but method1's method calls doesnt get tracked
method2() //tracked , , but method2's method calls doesnt get tracked and so on
Depedencies.stopTracking();
otherMethod() // not tracked as expected.
}
}
how to handle this case via ASM?
If you want to visit the contents of method1() and method2() you need to visit them separately, using the same technique you used to check Test.
If there is any recursion or inheritance going on, that might turn out to be tricky.
In the first case the problem lies in figuring out the stopping condition (to avoid infinite recursion), and in the second, figuring out what concrete implementation of the method to visit.

Pass outer anon class ref to a method in an inner anon class

How to pass outer anon class ref to a method in an inner anon class in Java?
I have a method that makes async call to a server - sendCall(some_args, callback). The callback is represented by anonymous class (let's name it OuterAnon) and contains a method for failure case. Inside this method a message box is created and sendCall() is called each time OK button is pressed. So I need to pass OuterAnon to the method again.
Here is a code to demonstrate what I mean:
private void sendCall(MyData data, OuterAnon<Boolean> callback){/*...*/}
private void myCall(final MyData data) {
sendCall(data, new OuterAnon<Boolean>() {
public void onFailure(Throwable throwable) {
final OuterAnon<Boolean> callback = this; //how to avoid this?
MessageBox.show(throwable.getMessage(), new MessageListener() {
public void process(MessageBox.OnClick action) {
if (action == MessageBox.OnClick.OK) {
sendCall(new MyData("resend?"), callback);
}
}
});
}
}
});
}
As you noticed, I take a ref for callback here:
final OuterAnon<Boolean> callback = this;
and use it here:
sendCall(new MyData("resend?"), callback);
But I want to avoid ref creation and pass callback like:
sendCall(new MyData("resend?"), this); //at the moment we point to MessageListener instead of OuterAnon.
Is there any way to do it in Java?
It's hard for us to fix since you've only shown incomplete code with classes that aren't supplied, so I don't know if this example is syntactically correct. That being said, a refactoring like this may suit your needs:
private void myCall(final MyData data)
{
sendCall(data, new OuterAnon<Boolean>()
{
public void onFailure(Throwable throwable)
{
showErrorMessage(throwable);
}
});
}
private void showErrorMessage(Throwable throwable)
{
MessageBox.show(throwable.getMessage(), new MessageListener()
{
public void process(MessageBox.OnClick action)
{
if (action == MessageBox.OnClick.OK)
{
sendCall(new MyData("resend?"));
}
}
});
}
private void sendCall(MyData data)
{
sendCall(data, this);
}
In general, I think it's a usually good idea to abstract code out of anon inner classes and into their own method on the enclosing class. It's now testable, reusable, and more readable, IMO.
If you really need to specify the onFailure inside the inner class the way you showed the code, and if you need to use that specific reference for callback, and you need to code this way...
Let's answer the question: no.
In my attempts, I've achieved 3 ways to access the anon-inner-least instance inside the anon-inner-most instance, but I think that none satisfies what you expect.
In that case, the anon-inner-most doesn't have a reference to the anon-inner-least: as you said, the this now points to the anon-inner-least.
Also, I tried to search at the java specification, but couldn't find exactly the answer to the question - if someone find the answer there, please contribute.
My try:
import java.util.ArrayList;
import java.util.LinkedList;
public abstract class AnonTest {
public static void main(String[] args) {
new ArrayList<Object>() {
private static final long serialVersionUID = -5986194903357006553L;
{
// initialize inner anon class
add("1");
}
// Way 1
private Object thisReference1 = this;
// Way 2
private Object getThisReference2() {
return this;
}
#Override
public boolean equals(Object obj) {
// Way 3
final Object thisReference3 = this;
new LinkedList<Object>() {
private static final long serialVersionUID = 900418265794508265L;
{
// initialize inner inner anon class
add("2");
}
#Override
public boolean equals(Object innerObj) {
// achieving the instance
System.out.println(thisReference1);
System.out.println(getThisReference2());
System.out.println(thisReference3);
System.out.println(this);
System.out.println();
// achieving the class
System.out.println(thisReference1.getClass());
System.out.println(getThisReference2().getClass());
System.out.println(thisReference3.getClass());
System.out.println(this.getClass());
System.out.println(this.getClass().getEnclosingClass());
return super.equals(innerObj);
}
}.equals("");
return super.equals(obj);
}
}.equals("");
}
}

How to handle public abstract boolean response

Like lots of askers on SO, I'm relatively new to java and have attempted to teach myself android programming with some decent success. I'm sure this is trivial to someone with actual knowledge on the subject. I'm working on a app that attempts to fetch data from the net and 'returns true' if you get the data and 'returns false' if it doesn't. I want to do something when it returns false but can't figure out how to properly handle the response. Right now, I just ignore the response an do nothing. Any help?
public void onBackPressed() {
Someclass.getinfo().maybeShowInfo(this);
finish();
}
What I would like to do is something like (in pseudo code)
public void onBackPressed() {
Someclass.getinfo().maybeShowInfo(this);
// if false is returned
// do something
// else
// finish();
}
public void onBackPressed() {
boolean result = Someclass.getinfo().maybeShowInfo(this);
if (result) {
finish();
} else {
// do something else
}
}
It looks to me like you've combined two things that must be separate. Make fetching the data and displaying two methods, by two classes.
private InfoDao infoDao; // This is a class that gets the data; it's a member of the class with the onBackPressed() method
public void onBackPressed() {
Info info = this.infoDao.find();
if (info != null) {
displayInfo();
}
}
public void onBackPressed()
{
boolean result = Someclass.getinfo().maybeShowInfo(this);
if (result = false)
{
//do work for false response;
}
else
{
finish();
}
}
don't forget that you have to make your Someclass.getinfo() return true if it succeded and false if it didn't.

Categories