how to instantiate T type inside a template class

2019-08-28 01:51发布

问题:

I have an abstract class abstract class MathFunc that is used to implement the mathematical functions Rastrigin, Griewangk and Rosenbrock in their specific classes final class Rastrigin extends MathFunc, final class Griewangk extends MathFunc and final class Rosenbrock extends MatjFunc.

This hierarchy of classes and how they are defined so far works flawlessly so I think there is no need to look for improvements on this area.

Now i have to implement another class Generation that will have some ArrayLists in it but the thing is I need to have a Generation implementation for each mathematical function described above. So that i need something like :

ArrayList<Rastrigin> rast = new ArrayList<>();
ArrayList<Griewangk> grie = new ArrayList<>();
ArrayList<Rosenbrock> rose = new ArrayList<>();

Inside these lists I have some Rastrigin/Griewangk/Rosenbrock objects that I need to instantiate.

I know from the past projects in C++ that I can use templates to specify a generic data type and I'm thinking that this is my solution. My implementation so far looks like this :

public class Generation <MathFunc> {
    private final ArrayList<MathFunc> pop = new ArrayList<>();
    private final ArrayList<MathFunc> nextpop = new ArrayList<>();
    private final ArrayList<MathFunc> Crossover = new ArrayList<>();

    Generation(MathFunc tp)
    {
        for(int i = 0; i < PopSize; i++)
        {
            pop.add(tp);
        }
    }
}

But the problem is: can i use the abstract class to instantiate the objects that rely on it ? Is there another way to do it ? I'm quite confused about the usage of templates.

But doing Generation(Mathfunc tp) seems a little weird to me since abstract classes are not instantiable.

P.S. This seems like a possible solution but i'm very not sure about it or how it actually works.

回答1:

If you want to reuse the same instance of a MathFunc I don't see any major flaws in your code (except that the generic definition of Generation should be Generation<T extends MathFunc).

So first change your class like this:

public class Generation <T extends MathFunc> {
  private final ArrayList<T> pop = new ArrayList<>();
  private final ArrayList<T> nextpop = new ArrayList<>();
  private final ArrayList<T> Crossover = new ArrayList<>();

  Generation(T tp)  {
    for(int i = 0; i < PopSize; i++) {
        pop.add(tp);
    }
  }
}

Then instantiate Generation like this:

Generation<Rastrigin> rastriginGen = new Generation<>(new Rastrigin());
Generation<Griewangk> griewangkGen = new Generation<>(new Griewangk());
Generation<Rosenbrock> rosenbrockGen = new Generation<>(new Rosenbrock());

If you want to use multiple instances of a MathFunc inside Generation you might want to use a factory pattern instead.

Factory interface:

interface MathFuncFuncFactory<T extends MathFunc> {
  T createFunc();
}

Then add implementations like RastriginFactory implements MathFuncFuncFactory<Rastrigin> etc.

Inside Generation:

Generation(MathFuncFactory<T> factory) {
  for(int i = 0; i < PopSize; i++) {
        pop.add(factory.createFunc());
    }
}

Constructor call:

Generation<Rastrigin> rastriginGen = new Generation<>(new RastriginFactory());


标签: java oop