【问题标题】:Initialize variable w same name depending on case根据大小写初始化具有相同名称的变量
【发布时间】:2014-01-30 11:52:55
【问题描述】:

所以我有这门课:

public class x {
ConsoleIO io = new ConsoleIO();

private Board board;
private boolean playing;

public x (String een, String twee) {
    this.board = new Board();
    if (een.toUpperCase().equals("C")) {
        Computer speler1 = new Computer(een);
    } else {
        Player speler1 = new Player(een);
    }
    if (twee.toUpperCase().equals("C")) {
        this.speler2 = new Computer(twee);
    } else {
        this.speler2 = new Player(twee);
    }
    this.playing = true;
}
}

如您所见,我想根据我提供的输入初始化变量 speler1 和 speler2。 显然这是行不通的。我知道我应该像这样预先初始化变量:

public class x {
ConsoleIO io = new ConsoleIO();

private Board board;
private boolean playing;
private Player speler1;
private Player speler2;

但是我仅限于 Player 类型,我不希望那样。有没有办法正确地做到这一点? *注:电脑是播放器的延伸。

【问题讨论】:

    标签: java class variables types initialization


    【解决方案1】:

    我的建议是声明Object

    private Object speler1;
    

    然后在你的 if 条件中:

    speler1 = new Computer(een);
    

    speler1 = new Player(een);
    

    现在,当您需要使用 speler1 时,只需使用这样的检查

    // if(speler1 instanceof Computer)
    if(speler1 instanceof Player)
        player1 = (Player)speler1;
    

    【讨论】:

    • 这行不通。 Computer 是 Player 的子类,因此 speler1 将始终是 Player 的 instanceof,即使它是 Computer。
    • 它会起作用的。例如 (Player extends Computer),对象将同时匹配 PlayerComputer,这是真的。你必须先检查Player,然后检查`Computer`。
    【解决方案2】:

    我的回答建立在 Sabuj 的基础上:

    我会尝试让 Computer 和 Player 实现一个通用接口,该接口定义了它们共享的方法。然后您可以使用该接口而不是Object。否则,如果您无论如何都不打算调用相同的方法,我认为以相同的方式命名一个变量是没有意义的:

    public interface Participant {
        public void makeMove();
    }
    public class Player implements Participant {...}
    public class Computer implements Participant {...}
    

    这允许类似的事情:

    Participant p;
    if (...) {
        p = new Player();
    } else {
        p = new Computer();
    }
    ...
    p.makeMove();
    

    您也许可以通过这种方式避免一些强制转换。

    【讨论】:

    • 听起来很有趣。可以举个例子吗?
    • 我编辑了我的答案(可能在您输入评论时),该示例是否解释了我的意思?如果没有,请告诉我哪些部分不清楚。
    • 但我需要播放器和计算机对象中的所有方法。这是否意味着我必须复制所有这些方法。 (我不熟悉“界面”)
    • 接口只是告诉实现该接口的任何类上哪些方法可用(这是一个相当普遍的 OOP 概念)。这就是为什么在上面的示例中没有实现 makeMove() 方法的原因。 Player 和 Computer 可能(并且很可能)对此方法有不同的实现。
    【解决方案3】:

    也许问题就在这里:

     if (een.toUpperCase().equals("C")) {
            Computer speler1 = new Computer(een);//delete here 'Computer'
        } else {
            Player speler1 = new Player(een);//delete here 'Player'
        }
    

    如果Computer扩展Player,为什么不先将speler1声明为Player,然后根据情况进行初始化?

    Player speler1;
    ...
    ...
    ...    
    
     if (een.toUpperCase().equals("C")) {
                speler1 = new Computer(een);
            } else {
                speler1 = new Player(een);
            }
    

    【讨论】:

    • 因为如果我以后在方法中创建一个临时变量:Computer speler = this.speler1; “无法从播放器转换为计算机”。
    • 如果Computer扩展了Player,则表示Computer的所有字段也在Player中。如果您声明一个 Player(比 Computer 更通用),您将能够使用 Player 实例(显然)设置该 Player 实例,也可以使用 Computer(因为所有 Computer 字段都在 Player 中)。也许你可以尝试做一个演员,比如 Computer speler = (Computer) this.speler1;
    【解决方案4】:

    不应该是这样吗:

    public class X {
        final ConsoleIO io = new ConsoleIO();
    
        private final Board board;
        private final Player player1;
        private final Player player2;
        private boolean playing;
    
        public X(String een, String twee) {
            this.board = new Board();
    
            if (een.toUpperCase().equals("C")) {
                this.player1 = new Computer();
            } else {
                this.player1 = new Human(een);
            }
    
            if (twee.toUpperCase().equals("C")) {
                this.player2 = new Computer();
            } else {
                this.player2 = new Human(twee);
            }
    
            this.playing = true;
        }
    }
    

    注意:

    HumanComputer 都是 Player 的子类。将常用方法/字段移动到 Player 基类中。如果你做得对,以后可能不需要区分ComputerHuman

    例如,Player 基类中可能有一个抽象方法move,它在子类中单独实现:Computer#move 使用算法计算下一步; Human#move 要求人类玩家输入下一步。因此,如果轮到player1,您只需调用player1.move(),无论是Human 还是Computer

    【讨论】:

    • 我试过了,但是变量仍然被识别为播放器类型
    • 不明白你的意思。当然,它们是 Player 对象。计算机扩展播放器,人类扩展播放器。
    • 不,如果我稍后在方法中创建一个临时变量:Computer speler = this.speler1; “无法从播放器转换为计算机”。
    • 为什么要这样做?如果您认为/设计面向对象,这应该不是必需的。见我上面的笔记。在极少数情况下,您仍然可以使用 instanceof 确定它是计算机还是人类。
    猜你喜欢
    • 2023-03-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-14
    • 1970-01-01
    • 2012-03-01
    • 2022-08-23
    相关资源
    最近更新 更多