简体   繁体   中英

Generic method with abstract class as parameter

Hi I am trying to create a generic method that takes in a parameter which type is an abstract parameterised class. Inside the method I want to create a instances of the passed parameter given it is a subclass of the abstract type since we cannot instantiate abstract classes.

However I am having some issues. And the error message says the RuleType cannot be resolved to a type which is not surprising anyway but I don't know how can I accomplish this. My current code is below.

private <F extends AbstractRule<T>, T> void applyRyle(F cRule,ArrayList<T> aFeatures)
{

    Class RuleType = cRule.getClass();


    // if the parameter passed is a subclass of AbstractRule create some objects
    if(!RuleType.getSuperclass().getName().equals("AbstractRule"))
    {
        ArrayList<RuleType<T>> aRules = new ArrayList<RuleType<T>>();
        for(int i = 0; i < 10; i++)
        {

            RuleType<T> aRule= new RuleType<T(pattern.getMatrices().size(), 2,aFeatures);
            aRule.initialise(aRule.getMaxLocalLevel());
            aRules.add(aRule);
        }
    }

Some of this can be done by using reflection:

private <F extends AbstractRule<T>, T> void applyRyle(F cRule, ArrayList<T> aFeatures)
{
     Class<? extends F> ruleType = cRule.getClass();
     // if the parameter passed is a subclass of AbstractRule create some objects
     if(! ruleType.getSuperclass().getName().equals("AbstractRule"))
     {
         ArrayList<? extends F> aRules = new ArrayList<? extends F>();
         for(int i = 0; i < 10; i++)
         {
             F aRule =
                 ruleType
                     .getConstructor(int.class, int.class, ArrayList.class)
                     .newInstance(pattern.getMatrices().size(), 2, aFeatures);
             aRule.initialise(aRule.getMaxLocalLevel());
             aRules.add(aRule);
         }
     }

though it's probably not the best way to accomplish what you really want.

Firstly, you don't need the following line, because your generic declaration guarentees that cRule will be an instance of AbstractRule .

if (!RuleType.getSuperclass().getName().equals("AbstractRule"))

The normal and better way of checking for the above at runtime would be to use instanceof

if (!cRule instanceof AbstractRule)

As for your ArrayList declarations you could just do the following:

ArrayList<F<T>> aRules = new ArrayList<F<T>>();

Note, however, that F is not the same as the actual solid class of aRule . F will be the type that the method was called with. That is, F will be wider than the class of aRule (it may include other subclasses of F that are not subclasses of the class of aRule ).

However, you cannot directly create new instances of F . You instead need to have some delegate method that will do it for you. That is, you cannot write new F() . What we could do though (since we already have a concrete instance of F ) is add an abstract method to AbstractRule that can create new instances of itself eg.

public interface AbstractRule<T extends AbstractRule> {
    T newRule(some parameters you need in the constructor);
}

Now we can write:

F newRule = aRule.newRule(pattern.getMatrices().size(), 2,aFeatures);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM