避免使用返回实现策略模式的泛型对象的工厂的原始类型警告

Avoid raw type warnings with a factory that returns a generic object implementing a strategy pattern

提问人:Codifier 提问时间:10/25/2020 更新时间:10/25/2020 访问量:398

问:

我的目标是拥有一个抽象类,其构造函数接受适用于派生类的抽象类。这个抽象类将实现适用于所有实现的泛型方法。你可以把 看作是实现一种策略模式,将方法委托给该模式。GameGameEngineGameGameGameGameEngineGame

因此,在使用 a 创建 时,我不在乎工厂返回什么实现。我只想确保使用适当的实现来构建实现。但是,如果我只是从工厂返回原始类型,我当然会收到警告。GameGameFactoryGameGameGameEngineGameRaw use of parameterized class 'Game'

此外,理想情况下,该方法不必传递类型,而只是根据 的某些属性推断类型。GameFactory.createGame(settings)settings

这是我所拥有的代码的要点:

public abstract class GameEngine<T extends Game<T>> {

  public void doSomethingAllEnginesUnderstand(T game);
}

public class LocalGameEngine
    extends GameEngine<LocalGame> {
}

public class RemoteGameEngine
    extends GameEngine<RemoteGame> {
}

public abstract class Game<T extends Game<T>> {

    private final GameEngine<T> gameEngine;

    protected Game(GameEngine<T> gameEngine) {
        this.gameEngine = gameEngine;
    }

    protected abstract T getSelf();
    
    public final void doSomethingAllEnginesUnderstand() {
      gameEngine.doSomethingAllEnginesUnderstand(getSelf());
    }
}

public class LocalGame 
    extends Game<LocalGame> {

    public LocalGame(LocalGameEngine gameEngine) {
        super(gameEngine);
    }

    @Override
    protected LocalGame getSelf() {
        return this;
    }
}

public class RemoteGame 
    extends Game<RemoteGame> {

    public RemoteGame(RemoteGameEngine gameEngine) {
        super(gameEngine);
    }

    @Override
    protected RemoteGame getSelf() {
        return this;
    }
}

public class GameFactory {

  // returns raw type Game
  public Game createGame(GameSettings settings) {
    if(settings.totalPlayers() > 1) {
      return new RemoteGame(new RemoteGameEngine());
    }
    else {
      return new LocalGame(new LocalGameEngine());
    }
  }
}

我是否滥用/误解泛型来达到我既定的目标?是否可以创建泛型类,同时仍然强制将适当的实现传递给构造函数?GameGameEngine

Java 泛型策略 模式 原始类型

评论

2赞 Louis Wasserman 10/25/2020
当你回来时会发生什么?Game<?>
0赞 Codifier 10/25/2020
我想避免进入这个话题,因为:“这很复杂”。;-)我已经尝试过了,但它的要点是我有复杂的代码和我自己的实现,这最终会抱怨,如果我进行嵌套调用。我对它的理解还不够,无法提出一个简洁的问题,所以我想看看我是否可以通过取消基类的泛型来简化我的代码。PromiseInferred type 'Game<capture<? extends Game<?>>>' for type parameter 'T' is not within its bound; should extend 'Game<Game<capture<? extends Game<?>>>>'Game
0赞 Louis Wasserman 10/25/2020
如果你想发挥作用,那就不行了。getSelf()
0赞 Codifier 10/25/2020
如果可能的话,我可以摆脱,但我认为这不是你的建议。正确?最终,实现必须只接受适当的实现,所以我想必须保留。除非我忽略了事情。getSelf()GameEngineGamegetSelf()

答:

1赞 Nikolas Charalambidis 10/25/2020 #1

我觉得你过度使用泛型,我发现矫枉过正。我会这样设计它:Game<T extends Game<T>>

  • make 和 extends(无泛型类型)。在以下情况下使用 polymorphysm:LocalGameRemoteGameGame@OverridegetSelf

    public class LocalGame extends Game {
    
        public LocalGame(LocalGameEngine gameEngine) {
             super(gameEngine);
        }
    
        @Override
        protected LocalGame getSelf() {
            return this;
        }
    }
    
    public class RemoteGame extends Game {
    
         public RemoteGame(RemoteGameEngine gameEngine) {
             super(gameEngine);
         }
    
         @Override
         protected RemoteGame getSelf() {
             return this;
         }
    }
    
  • Make 和 extends(无泛型类型)LocalGameEngineRemoteGameEngineGameEngine

    // actuyally, this abstract class can be an interface instead
    public abstract class GameEngine {
        public void doSomethingAllEnginesUnderstand(Game game) {}
    }
    
    public class LocalGameEngine extends GameEngine { }
    
    public class RemoteGameEngine extends GameEngine { }
    
  • make require any subclass of ,泛型部分只能在构造函数中使用,不需要制作整个泛型()。GameGameEngineGameGame<T>

    public abstract static class Game {
    
        private final GameEngine gameEngine;
    
        protected <T extends GameEngine> Game(T gameEngine) {
            this.gameEngine = gameEngine;
        }
    
        protected abstract Game getSelf();
    
        public final void doSomethingAllEnginesUnderstand() {
            gameEngine.doSomethingAllEnginesUnderstand(getSelf());
        }
    }
    
  • 整体变得简单:GameFactory

    public Game createGame(GameSettings settings) {
        if (settings.totalPlayers() > 1) {
                return new RemoteGame(new RemoteGameEngine());
        } else {
            return new LocalGame(new LocalGameEngine());
        }
    }
    

评论

1赞 Codifier 10/25/2020
是的,是的,是的!我觉得我也过度使用了泛型,并认为类似的事情应该是可能的。我只是不确定我是否可以像那样覆盖(使用子类型),也不知道我可以像那样为构造函数使用泛型类型。我唯一不完全确定的是,这种结构是否保证了权利始终用于正确的类型,但也许为了简单起见,我只需要放弃这种约束,因为这个解决方案似乎使我的代码变得不那么复杂。getSelf()GameEngineGame
1赞 Codifier 10/25/2020
我想我可能说得太早了;在我的热情中,我忘记了我希望特定的方法实现只接受它支持的实现。但是,在我的评论开始越来越没有意义之前,我必须更仔细地考虑一下,看看我是否可以通过您的答案(变体)来实现这些目标。我需要休息一下,当我对我的实际目标有了更清晰的了解时,我可能会回来。尽管如此,您的答案非常有用。GameEngineGame
1赞 Nikolas Charalambidis 10/25/2020
嗯。。我把问题加入书签,当我有满足所有要求的想法时再回来。