【问题标题】:Variables (possibly) get out of scope变量(可能)超出范围
【发布时间】:2016-01-09 23:36:17
【问题描述】:

好的,所以有两个类Player 和子类Classes。我使用子类通过 switch 语句在主类中设置玩家统计信息,让用户选择他的类。但是由于某种原因,设置变量在主类中执行时超出了范围。为了我的爱,我不知道为什么会这样

这是Player 类:

public class Player {
private int HP;
private int ATK;
private int DEF;
private int DAMAGE;

    void setHP(int a){
    HP=a;
    }

    void setATK(int a){
    ATK=a;
    }

    void setDEF(int a){
    DEF=a;
    }

    void setDAMAGE(){
    DAMAGE = damageCalculation();
    }

    int damageCalculation(){
    int damage = (2*ATK);    
    return damage;
    }

Player(String Class){
    Classes classes = new Classes();
switch(Class){
    case "Barbarian":
        classes.Barbar();
        System.out.println("Done");
        break;
        case "Rogue":
        break;
    default: System.out.println("Error");
}
}

void getStats(){
System.out.format("Player stats:"
        + "\nHP: %d"
        + "\nATK: %d"
        + "\nDEF: %d"
        + "\nDAMAGE: %d\n",HP,ATK,DEF,DAMAGE);
}
}

这是Classes 类(注意在子类中获取统计信息返回有效值):

public class Classes extends Player {

public void Barbar(){
Player player = new Player();   
player.setHP(60);
player.setATK(15);
player.setDEF(25);
player.setDAMAGE();
player.getStats();
 }
} 

这里是main 类:

import java.util.Scanner;
public class SurvivalGame {

   public static void main(String[] args) {
    Scanner scan = new Scanner(System.in,"Windows-1250");
    System.out.println("Enter your class");
    Player player = new Player(scan.nextLine());
    player.getStats(); //here getStats return zeros,
    //possibly out of scope variables if player enters Barbarian
 }
}

【问题讨论】:

  • 你期望 public void Barbar() 方法做什么?你在哪里称呼它?我想你希望它是一个构造函数,但构造函数不是这样的。
  • 因为您在 barbar 构造函数中创建了一个新的播放器实例,而不是使用父 Player

标签: java inheritance scope


【解决方案1】:
public void Barbar(){
Player player = new Player();   

如果您仔细观察,您正在创建一个新的 Player 并向其添加值,而不是 main 方法中的 Player。

【讨论】:

    【解决方案2】:

    当你扩展一个类时,你得到的东西是超类的一个实例,但是你选择在子类中添加额外的方法和字段。所以当你写

    public class Classes extends Player {
        //...
    }
    

    您的Classes 实例中已经包含HP(等)字段。您的Barbar 方法可以修改它们而无需创建Player 的新实例:

    public void Barbar(){
        setHP(60);
        setATK(15);
        setDEF(25);
        setDAMAGE();
        getStats();
    }
    

    你混淆了组合继承

    【讨论】:

    • 我试过你的解决方案,但调用时它仍然在主类中返回零,但在子类中它返回正确的值。
    【解决方案3】:

    您正在创建一个永远不会访问的 Player 的额外实例。只需浏览您的代码:

    /* Main Method */
    // You get a new Player object using direct user input
    // (Which is somewhat dangerous, you should do some data validation first)
    Player player = new Player(scan.nextLine())
    
    /* Player constructor */
    // Let's say user entered correctly "Barbarian". You are in the process of constructing
    // a new Player object when you call this:
    classes.Barbar();
    
    /* Barbar method */
    // The very first line creates a brand new player - different from one you were
    // in the process of constructing. 
    Player player = new Player(); 
    // Then you assign values to the new Player, which goes out of scope as soon as the
    // method ends. 
    

    而不是让Classes 扩展Player(老实说,这对我来说有点奇怪),我只是让 Barbar 方法属于 Player 类本身(然后可以在切换期间调用它陈述)。然后你可以直接修改当前 Player 的值,而不是依赖不同的类来为你做这件事。

    例如:

    public class Player 
    {
        public Player(String class)
        {
            switch (class)
            {
                case "Barbarian": 
                    Barbar();
                    break;
            }
        }
    
        public void Barbar()
        {
            HP = 60;
            ATK = 15;
            DEF = 25;
            setDAMAGE();
        }
    }
    

    【讨论】:

    • 我发现最好将所有播放器类放在单独的类中而不是有 10 页播放器类,但我想你的解决方案更优雅一些。
    猜你喜欢
    • 2018-09-19
    • 2016-04-30
    • 1970-01-01
    • 1970-01-01
    • 2016-03-05
    • 1970-01-01
    • 1970-01-01
    • 2021-10-04
    • 2020-12-24
    相关资源
    最近更新 更多