2017-01-30 9 views
2

У меня есть универсальный класс, который работает на других общих классах:Неконтролируемого предупреждение литого, когда две общие параметры имеют то же верхнюю грань

public abstract class DistributionService<TInput extends DistributionInputBase, 
           TContextProvider extends DistributionContextProviderBase, 
           TContext extends DistributionContextBase, 
           TStrategy extends DistributionStrategyBase, 
           TResult extends DistributionResultBase> { 
    private final TContextProvider _distributionContextProvider; 

    public DistributionService(TContextProvider distributionContextProvider){ 
     _distributionContextProvider = distributionContextProvider; 
    } 

    //@SuppressWarnings("unchecked") 
    public TResult GetResult(TInput input, TStrategy[] distributionStrategies){ 
     //unchecked cast warning 
     TContext context = (TContext)_distributionContextProvider.getContext(input); 
     TResult result = null; 

     for (TStrategy strategy: distributionStrategies){ 
      //unchecked cast warning 
      result = (TResult)strategy.Distribute(context); 
      if (result != null) 
       break; 
     } 

     return result; 
    } 
} 

и TContextProvider и TStrategy типов, которые разделяют одни и те же базовые типы в ограничениях (DistributionContextBase, DistributionResultBase):

public abstract class DistributionContextProviderBase<TContext extends DistributionContextBase, TInput extends DistributionInputBase> { 
    public abstract TContext getContext(TInput input); 
    public abstract int getOpenIssueCount(Workforce workforce); 
} 

public abstract class DistributionStrategyBase<TContext extends DistributionContextBase, TResult extends DistributionResultBase> { 
    protected WorkforceDistributionContext _context; 

    protected String GetReason(TResult result){ 
     String reason = GetReasonSub(result); 

     if (_context.HasRules()){ 
      reason += "\nRule(s) applied: " + _context.GetRules(); 
     } 

     return reason; 
    } 

    public abstract TResult Distribute(TContext context); 
    protected abstract TResult DistributeSub(TContext context); 
    protected abstract String GetReasonSub(TResult result); 
} 

, но я получаю «снят слепок» предупреждения, как отмечено в комментариях в классе DistributionService. Для меня, кажется, что она всегда гарантирует, что все типы будут выведены из базового класса, используемых в ограничениях:

TContext в DistributionService = TContext в DistributionContextProviderBase

TResult в DistributionService = TResult в DistributionStrategyBase

Я знаю, что можно избавиться от этого предупреждения с помощью @SuppressWarnings («unchecked»), но мне любопытно, есть ли другой способ сделать это правильно.

ответ

1

Объем параметра ограничен параметром class или способом, для которого он был определен. TContext не превосходит классы, хотя он, кажется, используется в обоих классах. Теперь, когда это не работает, давайте рассмотрим актуальную проблему.

Для меня, кажется, что она всегда гарантирует, что все типы будут получены из базовых классов, используемых в ограничениях:

Но будут типы по обе стороны уравнения, сопоставленных друг с другом всегда? Обратите внимание, что оператор distributionContextProvider.getContext(input); может возвращать DistributionContextBase или что-либо, что является его подклассом. В то же время TContext в DistributionService может быть заменен DistributionContextBase или что-либо, что является его подклассом.

Рассмотрим ситуацию, когда distributionContextProvider.getContext(input) возвращает DistributionContextBase но TContext в DistributionService замещено подкласса DistributionContextBase вместо этого. Следующий бросок приведет к ClassCastException и компилятор выполняет свою работу, и предупреждает вас о том же:

TContext context = (TContext)_distributionContextProvider.getContext(input); 
+1

ОК, имеет смысл, не понимал его первым. TContext может отличаться в DistributionService, чем в DistributionContextProviderBase. Я мог бы использовать DistributionContextBase context = (DistributionContextBase) _distributionContextProvider.getContext (input); но это, вероятно, больше проблема дизайна. Благодарю. – Robert