I'm using a library which provides custom View
s. I want to create a method that accepts only custom View
s from this library.
E.g. I have a PieChart
and a TableChart
. TableChart
extends LinearLayout
but PieChart
extends some internal abstract
chart which extends View
. So, I don't have any abstract class or interface that can describe both these objects.
Currently my method looks like this:
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;
// ...
}
}
So, I can actually pass any View
as a chart
parameter, which doesn't look good. I was thinking of creating some annotation such as @IntDef
in android but for class objects (https://developer.android.com/reference/android/support/annotation/IntDef.html). I looked at the source code and tried to create something similar but it didn't work. I'm still able to pass any View
as a parameter:
@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
I'm not really familiar with java annotations though. Does anybody know if this is possible to create such annotation that will allow to pass only specific classes as a parameter? Maybe there is some other approach to achieve type-safety? I can't change the source code of classes inside library.
Thanks.
EDIT
I provided PieChart
and TableChart
as examples. In my app I have about 10 types of charts.
So, after researching all possible solutions, I decided to use composition. I created my own wrappers around those charts and tables and then implemented my own 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() {
//...
}
// ...
}
So, my draw
method is now type-safe:
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;
// ...
}
}
Thanks everyone for your help.