我正在使用提供自定义View
的库。我想创建一个只接受来自此库的自定义View
的方法。
E.g。我有一个PieChart
和一个TableChart
。 TableChart
扩展了LinearLayout
,但PieChart
扩展了一些扩展abstract
的内部View
图表。所以,我没有任何可以描述这两个对象的抽象类或接口。
目前我的方法如下:
void draw(View chart, ChartData data) {
switch (data.getType()) {
case PIE_CHART:
PieChart<Numeric> pieChart = (PieChart<Numeric>) chart;
// ...
break;
case TABLE_CHART:
TableChart tableChart = (TableChart) chart;
// ...
break;
// ...
}
}
所以,我实际上可以将任何View
作为chart
参数传递,这看起来不太好。我在考虑在android中创建一些注释,例如@IntDef
,但是对于类对象(https://developer.android.com/reference/android/support/annotation/IntDef.html)。我查看了源代码并尝试创建类似的东西,但它不起作用。我仍然可以传递任何View
作为参数:
@Retention(RetentionPolicy.SOURCE)
@Target({ElementType.ANNOTATION_TYPE})
@interface ClassDef {
Class<? extends View>[] value() default {};
}
@Retention(RetentionPolicy.SOURCE)
@ClassDef({PieChart.class, TableChart.class})
@interface ChartView {}
void draw(@ChartView View chart, ChartData data) // doesn't work
我对Java注释并不熟悉。有没有人知道是否可以创建这样的注释,只允许将特定的类作为参数传递? 也许还有其他方法可以实现类型安全?我无法更改库中类的源代码。
感谢。
修改
我提供了PieChart
和TableChart
作为示例。在我的应用程序中,我有大约10种类型的图表。
答案 0 :(得分:1)
您可以定义两个公共方法,一个采用PieChart,另一个采用TableChart。这将为您提供类型安全。如果存在共享逻辑,则可以从公共方法中调用private或protected方法。注释方法不起作用。
答案 1 :(得分:1)
编写注释是一个不错的选择,因为它不需要您更改源代码,也不会产生任何运行时开销,并且它可以为您提供编译时保证客户端正确使用库。 / p>
仅仅编写注释是不够的。编译时,还需要提供注释处理器,如果您滥用注释,则会发出编译错误。因此,您展示的代码是一个良好的开端,但缺少注释处理器。
您可以编写自己的注释处理器,也可以使用现有的注释处理器。您可能觉得有用的一个是Checker Framework。它似乎非常适合您的用例:您可以使用Subtyping Checker并使用诸如
之类的命令编译代码javac -processor org.checkerframework.common.subtyping.SubtypingChecker \
-Aquals=ChartView MyFile.java
答案 2 :(得分:0)
您可以这样做的一种方法是:
void draw(View chart, ChartData data) throws Exception {
if(!(chart instanceof TableChart || chart instanceof PieChart)){
throw new IllegalArgumentException();
}
switch (data.getType()) {
case PIE_CHART:
PieChart<Numeric> pieChart = (PieChart<Numeric>) chart;
// ...
break;
case TABLE_CHART:
TableChart tableChart = (TableChart) chart;
// ...
break;
// ...
}
}
答案 3 :(得分:0)
因此,在研究了所有可能的解决方案之后,我决定使用构图。我在这些图表和表格周围创建了自己的包装器,然后实现了我自己的interface
:
interface AppChart {
void setupChart();
void bindChart(ChartData data);
}
class AppPieChart<T> implements AppChart {
private PieChart<T> chart;
public AppPieChart(PieChart<T> chart) {
this.chart = chart;
}
@Override
public void setupChart() {
//...
}
// ...
}
class AppTableChart implements AppChart {
private TableChart chart;
public AppTableChart(TableChart chart) {
this.chart = chart;
}
@Override
public void setupChart() {
//...
}
// ...
}
所以,我的draw
方法现在是类型安全的:
void draw(AppChart chart, ChartData data) {
switch (data.getType()) {
case PIE_CHART:
AppPieChart<Numeric> pieChart = (AppPieChart<Numeric>) chart;
// ...
break;
case TABLE_CHART:
AppTableChart tableChart = (AppTableChart) chart;
// ...
break;
// ...
}
}
感谢大家的帮助。