patternjavaMinor
Class for typecasting an Activity to an interface
Viewed 0 times
interfacefortypecastingactivityclass
Problem
In several places, I have some code that looks like the following, the only difference is in the type of listener.
To avoid duplication, I wrote this simple class:
And the previous code is simplified to the following:
But I do not like name
public class CustomFragment extends android.app.Fragment {
SomeListener listener;
@Override
public void onAttach(android.app.Activity activity) {
super.onAttach(activity);
// duplication
// ||
// \||/
// \/
try {
listener = (SomeListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement SomeListener");
}
}
}To avoid duplication, I wrote this simple class:
public class TypeConvertor {
private final Object whatNeedToCast;
public static TypeConvertor cast(Object whatNeedToCast) {
return new TypeConvertor(whatNeedToCast);
}
private TypeConvertor(Object whatNeedToCast) {
this.whatNeedToCast = whatNeedToCast;
}
public OtherType to(Class toWhichToCast) {
try {
return (OtherType) whatNeedToCast;
} catch (ClassCastException e) {
throw new ClassCastException(
whatNeedToCast.toString() + " must implement " + toWhichToCast.getName()
);
}
}
}And the previous code is simplified to the following:
public class CustomFragment extends android.app.Fragment {
SomeListener listener;
@Override
public void onAttach(android.app.Activity activity) {
super.onAttach(activity);
listener = TypeConvertor.cast(activity).to(SomeListener.class);
}
}But I do not like name
TypeConvertor. Help me pick a better name (and help refactor this simple class if needed).Solution
It seems to me like what you have done here is to create an entire class to avoid duplicating one line. (Or OK, 5 lines if counting the try-catch statement)
I don't agree with the need to create a class for this. Especially not a generic one, since this line of code:
Does the same thing as:
So all you are doing additionally is to wrap it in another exception which is explained just slightly better. But personally, I think this message...
com.yourpackage.YourActivity@1df59a42 must implement com.yourpackage.SomeListener
...actually says just as much as the default one, if you would not catch the exception in the first place:
java.lang.ClassCastException: Cannot cast com.yourpackage.YourActivity to com.yourpackage.SomeListener
Actually,
If you are writing these classes to be used as a library by many other people, then it could be good practice to explain that the activity must implement some interface. Otherwise, I don't see the point of it. But either way, there's no need to create an entire class for this.
Summary:
Get rid of your additional class, just cast your
So in the end, all that remains is this one line:
And it's perfectly OK to duplicate that.
I don't agree with the need to create a class for this. Especially not a generic one, since this line of code:
return (OtherType) whatNeedToCast;Does the same thing as:
return OtherType.class.cast(whatNeedToCast);So all you are doing additionally is to wrap it in another exception which is explained just slightly better. But personally, I think this message...
com.yourpackage.YourActivity@1df59a42 must implement com.yourpackage.SomeListener
...actually says just as much as the default one, if you would not catch the exception in the first place:
java.lang.ClassCastException: Cannot cast com.yourpackage.YourActivity to com.yourpackage.SomeListener
Actually,
Cannot cast (class) to (class) would say even more if you would override the toString method in YourActivity.If you are writing these classes to be used as a library by many other people, then it could be good practice to explain that the activity must implement some interface. Otherwise, I don't see the point of it. But either way, there's no need to create an entire class for this.
Summary:
Get rid of your additional class, just cast your
activity to SomeListener and don't catch the exception to throw your own.So in the end, all that remains is this one line:
listener = (SomeListener) activity;And it's perfectly OK to duplicate that.
Code Snippets
return (OtherType) whatNeedToCast;return OtherType.class.cast(whatNeedToCast);listener = (SomeListener) activity;Context
StackExchange Code Review Q#39091, answer score: 6
Revisions (0)
No revisions yet.