我正在尝试使用类型化回调实现抽象片段,以便在多个子类中使用它。
如何检查Context是否是适当类的实例?
我的抽象代码CallbackFragment:
public abstract class CallbackFragment<C> extends Fragment {
protected C mCallback;
public CallbackFragment() {
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
//just in case
if(context == null)
throw new NullPointerException();
try {
mCallback = (C) context; //this line not seems to throw any exception
} catch (ClassCastException exception) {
throw new RuntimeException(context.toString() + " must implement Callbacks");
}
}
@Override
public void onDetach() {
super.onDetach();
mCallback = null;
}
}
车辆清单片段:
public abstract class VehicleListFragment<T extends Vehicle>
extends CallbackFragment<VehicleListFragment.Callback<T>> {
//callback for any list of any vehicle
public interface Callback<T extends Vehicle> {
void onListItemSelected(T selectedItem);
}
//common code for list of any vehicle
public VehicleListFragment() {
}
}
巴士,卡车,船,自行车,无论是什么列表片段:
public class BusListFragment
extends VehicleListFragment<Bus> {
//code specific for list of bus
public BusListFragment() {
}
}
车辆详细信息片段:
public abstract class VehicleDetailsFragment<T extends Vehicle, C extends VehicleDetailsFragment.Callback<T>>
extends CallbackFragment<C> {
//common methods of callback for any vehicle
public interface Callback<T> {
void onVehicleEdited(T editeItem);
}
//common code for any vehicle
public VehicleDetailsFragment() {
}
}
巴士,卡车,船,自行车,无论细节如何:
public class BusDetailsFragment
extends VehicleDetailsFragment<Bus, BusDetailsFragment.Callback> {
//specific for Bus methods
public interface Callback
extends VehicleDetailsFragment.Callback<Bus> {
void onSomethingSpecificForBusHappened(Bus bus);
}
//code specific for Bus
public BusDetailsFragment() {
}
}
我试图为CallbackFragment添加一个抽象方法来获取回调类:
public abstract class CallbackFragment<C> extends Fragment {
...
@NonNull
protected abstract Class<C> getCallbackClass();
@Override
public void onAttach(Context context) {
super.onAttach(context);
...
//now checking instanceof like this
if(!getCallbackClass().isAssignableFrom(context.getClass())){
throw new RuntimeException(context.toString() + " must implement Callbacks");
}
}
}
使用BusDetailsFragment,一切看起来都不错:
public class BusDetailsFragment
extends VehicleDetailsFragment<Bus, BusDetailsFragment.Callback> {
@NonNull
@Override
protected Class<Callback> getCallbackClass() {
return Callback.class;
}
...
}
但不是BusListFragment:
public class BusListFragment
extends VehicleListFragment<Bus> {
@NonNull
@Override
protected Class<Callback<Bus>> getCallbackClass() {
/**
* I'm not seeing any option here
*
* mCallback - is null yet. So, there is no way to use mCallback.getClass()
*
* Callback<Bus>.class - Cannot select from parameterized type
*/
//return mCallback.getClass();
//return Callback<Bus>.class;
}
...
}
当然,我可以为VehicleListFragment的每个子类创建一个自己的接口,扩展VehicleListFragment.Callback(就像在VehicleDetailsFragment的子类中一样),但它总是如下所示:
public interface Callback
extends VehicleListFragment.Callback<Bus> {
//nothing more here
}
这对我来说不是最好的选择。 也许有其他解决方案?请分享您的想法。任何帮助将不胜感激。
答案 0 :(得分:2)
mCallback = (C) context; //this line not seems to throw any exception
此调用永远不会抛出异常。在运行时,C
替换为Object
(称为类型删除) - 一切都是Object
。因此,您可以在此时指定任何内容。
要在您需要的地点进行异常(或至少是错误确定),您可以使用:
public abstract class CallbackFragment<C> extends Fragment {
protected C mCallback;
protected Class<C> callbackClass;
public CallbackFragment(Class<C> clazz) {
this.callbackClass = clazz;
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
//just in case
if(context == null)
throw new NullPointerException();
if (clazz.isAssignableFrom(context.getClass()){
mCallback = (C) context;
}else{
//oops
}
}
}
OFC。然后你的FragmentCreation会改变
CallbackFragment<Something> fragment = new CallbackFragment<Something>();
到
CallbackFragment<Something> fragment = new CallbackFragment<Something>(Something.class);
它有点不同,但允许您随时保留跟踪实际类型,绕过类型擦除。
ps。:对于 Inherited 类,您可以更通用:
public abstract class CallbackFragment<C> extends Fragment {
protected Class<C> callbackClass;
public CallbackFragment() {
this.callbackClass = (Class<C>) ((ParameterizedType) getClass()
.getGenericSuperclass()).getActualTypeArguments()[0];;
}
}
public class CallbackFragmentOfSomething extends <CallbackFragment<Something>>{
}
这只会失败,如果您的实际类由于继承而未定义,但是“在运行中”:
CallbackFragment<Something> fragment = new CallbackFragment<Something>();
(一切未经测试/没有复制粘贴,但应该有些准确)