Java- How do I gather classes by using enum?
Let's assume that I have lots of implementations of matrices (Which don't extend from one to another) and I want the user to be able to see all th开发者_如何转开发e different classes, to gather them in some kind of enum or something, How can I do that? It doesn't have to be a menu or something, just so I will be able to see all the classes, just like enum.
For example:
MainMatrix matrix= new (ALL THE POSSIBILITIES)();
While the MainMatrix is the common interface of all matrices.
Can I use enum that will create instance of new class matching the option I'll choose? for example:
public enum Matrices{
DIAGONAL_MATRIX(new DiagonalMatrix());
..
..
}
Can I do that?
Here a solution using an enum with an abstract method:
public enum MatrixFactory {
/**
* Creates a diagonal matrix
*
* args[0] : a double[] with the diagonal values
*/
DIAGONAL_MATRIX {
@Override
public MainMatrix create(Object[] args) {
double[] diagonal = (double[]) args[0];
return new DiagonalMatrix(diagonal);
}
},
/**
* Creates a full matrix
*
* args[0] : the number of rows
*
* args[1] : the number of columns
*/
FULL_MATRIX() {
@Override
public MainMatrix create(Object[] args) {
int rows = (Integer) args[0];
int cols = (Integer) args[1];
return new FullMatrix(rows, cols);
}
};
public abstract MainMatrix create(Object[] args);
}
Usage:
MatrixFactory.DIAGONAL_MATRIX.create(new Object[] {new double[] {1.0, 2.0, 3.0}});
MatrixFactory.FULL_MATRIX.create(new Object[] {4, 4});
See also the classic enum tutorial which illustrates this with an arithmetic enum:
public enum Operation {
PLUS { double eval(double x, double y) { return x + y; } },
MINUS { double eval(double x, double y) { return x - y; } },
TIMES { double eval(double x, double y) { return x * y; } },
DIVIDE { double eval(double x, double y) { return x / y; } };
// Do arithmetic op represented by this constant
abstract double eval(double x, double y);
}
I advocate a regular factory though, because the usage is much clearer. Using an enum does not add any benefits I can think of in this context.
public class MatrixFactory {
/**
* Creates a diagonal matrix
*
* @param diagonal the diagonal values
* @return
*/
public static MainMatrix diagonalMatrix(double[] diagonal) {
return new DiagonalMatrix(diagonal);
}
/**
* Creates a full matrix
*
* @param rows the number of rows
* @param cols the number of columns
* @return
*/
public static MainMatrix fullMatrix(int rows, int cols) {
return new FullMatrix(rows, cols);
}
}
Usage:
MatrixFactory.diagonalMatrix(new double[] {1.0, 2.0, 3.0});
MatrixFactory.fullMatrix(4, 4);
You can do this programmatically with the Reflections library.
For example:
Reflections reflections = new Reflections(...); //see in other use cases
Set<Class<? extends MainMatrix>> subTypes =
reflections.getSubTypesOf(MainMatrix.class);
We can create some kind of Matrix Factory:
public class MatrixImplFactory {
IMatrixImpl createMatrix(double[] diagonal) {
return new DiagonalMatrix(diagonal);
}
IMatrixImpl createMatrix(int rows, int cols) {
return new FullMatrix(rows, cols);
}
}
I just need to make sure that each matrix will have different type of constructor.
Making instance of a matrix in this way:
public class Matrix implements IMatrix {
protected IMatrixImpl impl;
MatrixFacotry factory;
public Matrix(int rows, int cols) {
impl = factory.createMatrix(rows, cols);
}
....
}
I think this might be what you want to try:
public enum Matricies {
DIAGONAL_MATRIX(new DiagonalMatrix()),
OTHER_MATRIX(new OtherMatrix(4, 4));
private MainMatrix value; // each value of the enum has a value which is an instance of a matrix
Matricies(MainMatrix val) { // enum constructor to set instance of matrix
value = val;
}
public MainMatrix getValue() {
return value;
}
}
To get instance of diagonal matrix:
MainMatrix diagMatrix = Matricies.DIAGONAL_MATRIX.getValue();
One way is to have a method in your enum to create the matrix (mostly based on what you already wrote):
public enum Matrices{
DIAGONAL_MATRIX {
@Override
public MainMatrix createMatrix() {
return new DiagonalMatrix();
}
},
OTHER_MATRIX {
@Override
public MainMatrix createMatrix() {
return new OtherMatrix();
}
},
...
;
public abstract MainMatrix createMatrix();
}
EDIT:
just call the createMatrix
method to create a matrix for a given enum:
Matrices type = ...
MainMatrix matrix = type.createMatrix();
or directly
MainMatrix matrix = DIAGONAL_MATRIX.createMatrix();
- Write the above code in Eclipse
- Put the cursor within the text
MainMatrix
- Press
F4
.
F4
is the Eclipse shortcut to open the 'Type Hierarchy' view. This will show you all sub-types of the currently selected type.
If all the classes are implementations of matrices, then it probably makes sense to have them implement a common interface, or extend a common abstract class. With this simple 2 level hierarchy, you can also build an array of the common super-class/interface. Here's an example of what I mean:
public class AA {
public interface MainMatrix {
}
public class MatrixA implements MainMatrix {
}
public class MatrixB implements MainMatrix {
}
public void go() {
MainMatrix[] mainMatrices = new MainMatrix[2];
mainMatrices[0] = new MatrixA();
mainMatrices[1] = new MatrixB();
}
}
精彩评论