我尝试定义一个包装android.view.View
及其子类的类,并包含一些关于渲染的信息(人们可能将其称为View Model或PresentationModel)。
public class MyClass<T extends View>
{
private T view;
private Blah blah;
}
我的原始问题是我是否应该对视图变量的类型进行参数化。 Java的通用实现似乎相当简单(例如,所有类型参数信息在编译时都被删除),我可以在这里找到两个可能的优点。
1)即使我仍然需要在我的代码中的某处指定类型,向下倾斜看起来更酷。
@SuppressWarnings("unchecked")
public final <U extends View> U getView()
{
return (U) view;
}
以上,
Button btn = (Button) obj.getView();
((LinearLayout) obj).addView(view);
变为
Button btn = obj.getView();
obj.<LinearLayout>addView(view);
2)我或许可以编写一些多态代码;
@Override
public void bringToFront()
{
// stuff
}
如果某个子类重新定义了一个方法,
public final T getView()
{
return view;
}
以上,
obj.bringToFront();
可能会有不同的行为,具体取决于我们提供的类型参数。最大的问题是我不知道Google的android框架中是否存在任何实际覆盖情况。
目前,我不会使用Generics,因为显然我不能将HashMap
与泛型类一起使用。
Map<String, MyClass<View>> objs = new HashMap<String, MyClass<View>>();
MtClass<Button> obj = objs.get(key); // type mismatch
答案 0 :(得分:2)
2)不正确,至少在你的例子中。您提供的功能不是多态的,因此基于T
不会有所不同。当然,子类可以重新定义行为,但这与T
无关。
对于1),是的,它确实使代码更漂亮,但它也使它更加不可取。考虑到您拥有视图T
的类型,为什么要将其转换为U
?根据您上面给出的代码,这显然是非法的,如果您没有强制转换,它将是编译时错误,但现在只是一个运行时错误,除非类型恰好匹配。即如果您有MyClass<Button>
并定义了T getView()
,则代码可以在不使用U
强制转换的情况下使用,或者根本使用类型参数U
,而MyClass<TextView>
则会在getView()
上导致运行时错误,尽管它正确编译。
关于最后一点,当您从Map<K, V>
检索对象时,您只能证明该对象是V
,而不是V
的子类型,这就是为什么最后一个例子没有编译。
总的来说,泛型用于增加代码重用,同时强制执行类型安全,但是您提供的示例似乎只执行前者,并且将类型安全性抛出窗口(公平地说,就是Android UI编程一般来说)。在您给出的示例中,似乎仿制药不会对您造成太大伤害。