当前位置: 首页 > 面试题库 >

循环泛型(尝试2)

壤驷睿
2023-03-14
问题内容

第二次尝试解决此问题(初始代码不足以突出该问题)

这是无法编译的代码:

interface Player<R, G extends Game>
{
    R takeTurn(G game);
}

interface Game<P extends Player>
{
    void play(P player);
}

abstract class AbstractGame<R, P extends Player>
    implements Game<P>
{
    public final void play(final P player)
    {
        final R value;

        value = player.takeTurn(this);
        turnTaken(value);
    }

    protected abstract void turnTaken(R value);
}

public class XPlayer
    implements Player<Integer, XGame>
{
    @Override
    public Integer takeTurn(final XGame game)
    {
        return (42);
    }
}

public class XGame<P extends Player<Integer, XGame>>
    extends AbstractGame<Integer, XPlayer>
{
    @Override
    protected void turnTaken(final Integer value)
    {
        System.out.println("value = " + value);
    }
}

public class Main
{
    public static void main(final String[] argv) 
    {
        final XPlayer player;
        final XGame   game;

        player = new XPlayer();
        game   = new XGame();
        game.play(player);
    }
}

我遇到的是试图让AbstractGame中的play方法进行编译。似乎我必须与Game和Player一起在扩展/实现中添加泛型,但我一生都无法理解。

play方法必须在AbstractGame类中是最终方法,并且无法进行强制转换,而且我不想编写另一种方法(如turnTaken)来使它能够正常工作。

编辑:这里要求的是编译的代码,但需要强制转换:

interface Player<R, P extends Player<R, P, G>, G extends Game<R, G, P>>
{
    R takeTurn(G game);
}

interface Game<R, G extends Game<R, G, P>, P extends Player<R, P, G>>
{
    void play(P player);
}

abstract class AbstractGame<R, G extends Game<R, G, P>, P extends Player<R, P, G>>
    implements Game<R, G, P>
{
    public final void play(final P player)
    {
        final R value;

        value = player.takeTurn((G)this);
        turnTaken(value);
    }

    protected abstract void turnTaken(R value);
}

class XPlayer
    implements Player<Integer, XPlayer, XGame>
{
    @Override
    public Integer takeTurn(final XGame game)
    {
        return (42);
    }
}

class XGame
    extends AbstractGame<Integer, XGame, XPlayer>
{
    @Override
    protected void turnTaken(final Integer value)
    {
        System.out.println("value = " + value);
    }
}

class Main
{
    public static void main(final String[] argv) 
    {
        final XPlayer player;
        final XGame   game;

        player = new XPlayer();
        game   = new XGame();
        game.play(player);
    }
}

问题答案:

混合泛型和原始类型是行不通的。如果需要这些接口互相引用,则它们还需要引用自己:

interface Player<R, P extends Player<R, P, G>, G extends Game<R, G, P>>
{
    R takeTurn(G game);
}

interface Game<R, G extends Game<R, G, P>, P extends Player<R, P, G>>
{
    void play(P player);
}

尽管这看起来很头疼,但我不确定您为什么需要它。

编辑:

我能够AbstractGame根据以上内容实施您的操作:

abstract class AbstractGame<R, P extends Player<R, P, AbstractGame<R, P>>>
    implements Game<R, AbstractGame<R, P>, P>
{
    public final void play(final P player)
    {
        final R value;

        value = player.takeTurn(this);
        turnTaken(value);
    }

    protected abstract void turnTaken(R value);
}

但是我不能XGame和和完全关闭电路XPlayer

public class XGame
    extends AbstractGame<Integer, XPlayer> //compile error on XPlayer
{

    protected void turnTaken(Integer value) { }
}

public class XPlayer
    implements Player<Integer, XPlayer, XGame> //compile error on XGame
{
    @Override
    public Integer takeTurn(final XGame game)
    {
        return (42);
    }
}

这个问题似乎是每个通用声明XGameXPlayer需要对方是正确的。这是您的设计真正具有周期性的地方。如果编译器“假定”每一个都是正确的,那么理论上它将起作用。但事实并非如此。

编辑2:

这个怎么样:

interface Game<R, G extends Game<R, G>>
{
    void play(Player<R, G> player);
}

interface Player<R, G extends Game<R, G>>
{
    R takeTurn(G game);
}

abstract class AbstractGame<R, G extends AbstractGame<R, G>>
    implements Game<R, G>
{
    public final void play(final Player<R, G> player)
    {
        final R value;

        value = player.takeTurn(self());
        turnTaken(value);
    }

    protected abstract G self();

    protected abstract void turnTaken(R value);
}

public final class XGame extends AbstractGame<Integer, XGame>
{
   protected XGame self() {
      return this;
   }

   protected void turnTaken(Integer value) { }
}

public class XPlayer implements Player<Integer, XGame>
{
    @Override
    public Integer takeTurn(final XGame game)
    {
       return (42);
    }
}

这里的关键是声明一个html" target="_blank">抽象方法self()AbstractGame该方法返回type的实例G。扩展类必须使用自己的类型解析继承的类型参数,并实现self()return
this。这仅适用于内部代码,因为扩展类很容易说谎,例如:

public class EvilGame extends AbstractGame<Integer, AnotherGame> { ... }


 类似资料:
  • 问题内容: 我正在尝试采取以下措施: 和 我要坚持的是我需要在Game和Player界面中进行哪些更改才能使仿制药正常工作(我停顿了一下,但头上还有些毛:-)特别是,我迷上了Player需要在哪里进行操作知道游戏的类型,并且游戏需要知道玩家的类型。 问题答案: 这不是泛型问题(Game未键入)。 这是一个继承问题。尝试这个:

  • 问题内容: 下面的代码询问用户他/她想要多少个赛车手。 如果在代码中输入数字,则代码会跳出循环,并且程序的其余部分可以正常运行;但是,当我输入诸如“ awredsf”之类的内容时,它应该捕获该异常,并且确实如此。它没有连续提示用户,而是连续循环,这对我来说没有意义。 连续循环时,程序打印如下: 多少赛车手应该参加比赛?多少赛车手应该参加比赛?多少赛车手应该参加比赛?多少赛车手应该参加比赛?多少赛车

  • 问题内容: 我有一个看起来像这样的循环: 这是方法的主要内容,其唯一目的是返回浮点数数组。我希望此方法在出现错误时返回,因此我将循环放在一个块中,如下所示: 但是后来我也想到将块放入循环中,如下所示: 是否出于某种原因(无论是性能还是其他原因)偏爱一个? 编辑: 共识似乎是将循环放在try / catch中(可能在其自己的方法中)更干净。但是,仍然存在关于哪个更快的争论。有人可以测试一下并返回统一

  • 问题内容: 有人可以向我解释为什么明显需要为ForEachLoop实例分配通用类型吗? 为什么编译器会抱怨: 类型不匹配:无法从元素类型Object转换为String ? JDK 1.5.0_09 问题答案: 这是一个很常见的错误: 应该 如果您使用原始类型(不应这样做),则编译器将擦除该实例的所有通用信息,即使它不是类型参数T,也使其与1.5版之前的代码兼容。 仅在使用Java 1.4或更低版本

  • 问题内容: 我有一个while循环,应该捕获一个非整数输入,并要求用户重新输入一个整数。但是,它只是无限循环错误消息。有谁知道为什么不允许第二次扫描仪输入? 问题答案: 当您输入的令牌不是数字时,调用nextInt不会将扫描仪移到令牌之外。结果,它只是一遍又一遍地读取相同的令牌。 这是nextInt的文档:http : //download.oracle.com/javase/6/docs/api