patternjavaMinor
Super class knowing the type of its children? Surely there is a better way
Viewed 0 times
childrenthesuperwaybettertypeitsknowingthereclass
Problem
I'm working on a small project that does mathematical calculations based on selected data in a JTable. The goal is to make the program fairly adaptable for adding new mathematical calculations in the future. For reference, some of the current calculations are: calculating the mean (average) of a set of data; calculating the percentile of each item in a set of input data; calculating the least squares linear regression (best fit linear function) for a set of data points.
My current design thought process is that to make things the math utilities flexible, there needs to be a some type of base class for analysis data that serves as input and output to some type of
Then, something for calculating
```
public class DataAnalysisMean implements IDataAnalysis {
AnalysisDataType getInputDataType() { return AnalysisDataType.Set; }
AnalysisDataType getInputDataType() { return AnalysisDataType.Scalar; }
IAnalysisData performAnalysis(IAnalysisData intputData) {
IAnalysisDataSet inputDataSet = (IAnalysisDataSet)inputData;
double sum = 0;
for (int i = 0; i < inputDataSet.getCount(); i++) {
IAnalysisData dataItem = inputDataSet.getData(i);
IAnalys
My current design thought process is that to make things the math utilities flexible, there needs to be a some type of base class for analysis data that serves as input and output to some type of
performAnalysis function in a base class for all analysis classes. This lead me to a skeleton design as follows:public enum AnalysisDataType {
Scalar,
Set,
Map
}
public interface IAnalysisData {
AnalysisDataType getType();
}
public interface IAnalaysisDataScalar extends IAnalysisData {
double getValue();
}
public interface IAnalaysisDataSet extends IAnalysisData {
int getCount();
IAnalysisData getData(int index);
}
public interface IAnalaysisDataMap extends IAnalysisData {
IAnalysisData getDomain();
IAnalysisData getCodomain();
}
public interface IDataAnalysis {
AnalysisDataType getInputDataType();
AnalysisDataType getOutputDataType();
IAnalysisData performAnalysis(IAnalysisData inputData);
}Then, something for calculating
mean would be:```
public class DataAnalysisMean implements IDataAnalysis {
AnalysisDataType getInputDataType() { return AnalysisDataType.Set; }
AnalysisDataType getInputDataType() { return AnalysisDataType.Scalar; }
IAnalysisData performAnalysis(IAnalysisData intputData) {
IAnalysisDataSet inputDataSet = (IAnalysisDataSet)inputData;
double sum = 0;
for (int i = 0; i < inputDataSet.getCount(); i++) {
IAnalysisData dataItem = inputDataSet.getData(i);
IAnalys
Solution
First, I get some error messages when I put this in the compiler.
I had to replace the anonymous inner class that is returned by
Second, I'm thinking generics would solve this quite nicely.
I agree that the parent class should not need to know it's child classes, but it can obtain this data; see the methods that I have commented out. I have commented them out because I don't like them, but still want to show that it's possible. I'll admit that using
I had to replace the anonymous inner class that is returned by
performAnalysis with a helper class. I'm not a fan of helper classes like this, so it would be nice if someone else had a better idea.Second, I'm thinking generics would solve this quite nicely.
I agree that the parent class should not need to know it's child classes, but it can obtain this data; see the methods that I have commented out. I have commented them out because I don't like them, but still want to show that it's possible. I'll admit that using
.class is a bit tricky when using generics, because of type erasure. However, as long as the generic types are known at compile time, this should not be a problem.interface IDataAnalysis {
// public Class getInputDataType( );
// public Class getOutputDataType( );
OutputType performAnalysis(InputType inputData);
}
public class DataAnalysisMean implements IDataAnalysis {
//
// public Class getInputDataType( ) { return IAnalysisDataSet.class; }
// public Class getOutputDataType( ) { return IAnalysisDataScalar.class; }
public IAnalysisDataScalar performAnalysis(IAnalysisDataSet inputData) {
IAnalysisDataSet inputDataSet = (IAnalysisDataSet)inputData;
double sum = 0;
for (int i = 0; i < inputDataSet.getCount(); i++) {
IAnalysisData dataItem = inputDataSet.getData(i);
IAnalysisDataScalar dataItem2 = (IAnalysisDataScalar)dataItem;
sum += dataItem2.getValue();
}
return new HelperClass( inputDataSet, sum );
}
private class HelperClass implements IAnalysisDataScalar
{
IAnalysisDataSet inputDataSet;
double sum = 0;
HelperClass( IAnalysisDataSet inputSet, double sum )
{
this.inputDataSet = inputSet;
this.sum = sum;
}
@Override
public double getValue() {
return sum / inputDataSet.getCount();
}
@Override
public AnalysisDataType getType() {
return AnalysisDataType.Scalar;
}
}
}Code Snippets
interface IDataAnalysis<InputType extends IAnalysisData, OutputType extends IAnalysisData> {
// public Class<?> getInputDataType( );
// public Class<?> getOutputDataType( );
OutputType performAnalysis(InputType inputData);
}
public class DataAnalysisMean implements IDataAnalysis<IAnalysisDataSet, IAnalysisDataScalar> {
//
// public Class<?> getInputDataType( ) { return IAnalysisDataSet.class; }
// public Class<?> getOutputDataType( ) { return IAnalysisDataScalar.class; }
public IAnalysisDataScalar performAnalysis(IAnalysisDataSet inputData) {
IAnalysisDataSet inputDataSet = (IAnalysisDataSet)inputData;
double sum = 0;
for (int i = 0; i < inputDataSet.getCount(); i++) {
IAnalysisData dataItem = inputDataSet.getData(i);
IAnalysisDataScalar dataItem2 = (IAnalysisDataScalar)dataItem;
sum += dataItem2.getValue();
}
return new HelperClass( inputDataSet, sum );
}
private class HelperClass implements IAnalysisDataScalar
{
IAnalysisDataSet inputDataSet;
double sum = 0;
HelperClass( IAnalysisDataSet inputSet, double sum )
{
this.inputDataSet = inputSet;
this.sum = sum;
}
@Override
public double getValue() {
return sum / inputDataSet.getCount();
}
@Override
public AnalysisDataType getType() {
return AnalysisDataType.Scalar;
}
}
}Context
StackExchange Code Review Q#5303, answer score: 2
Revisions (0)
No revisions yet.