开发者

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();


  1. Write the above code in Eclipse
  2. Put the cursor within the text MainMatrix
  3. 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();
    }

}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜