【问题标题】:Instance of a Method in a Separate Class/Method?单独的类/方法中的方法实例?
【发布时间】:2012-12-25 04:49:46
【问题描述】:

我正在创建一个最终幻想角色的小游戏,在其中我输入我想“战斗”的人的名字我将每个角色(只有 5 个)作为一个名为 Stats 的超类的子类,其中定义了变量(非静态)和 getter/setter。

代码都可以按我的意愿运行,但我不喜欢它都在一个巨大的类中。

Main方法在这里;

package com.George.revision;

import java.util.Random;

import com.George.characters.Cloud;
import com.George.characters.Squall;
import com.George.characters.Stats;
import com.George.characters.TheEnemy;
import com.George.characters.ThePlayer;
import com.George.characters.Tidus;
import com.George.characters.Yuna;
import com.George.characters.Zidane;
import com.George.input.GetInput;
import com.George.input.ListNames;



public class Main {


    public static void main(String[] args) {

        ListNames.listNames();


        Stats clo = new Cloud();
        Stats squ = new Squall();
        Stats zid = new Zidane();
        Stats tid = new Tidus();
        Stats yun = new Yuna();

        String versus = GetInput.getInput("\nWhich of these Characters would you like to go up against?");

        Stats ene1 = new TheEnemy();


        switch (versus) {
        case "Cloud":
            ene1.setName(Names.CLOUD);
            ene1.setHairColor(Stats.BLONDE);
            ene1.setWep(Weapons.BUSTER_SWORD);
            ene1.setSkill(clo.skill);
            ene1.setAp(clo.ap);
            ene1.setStr(clo.str);
            ene1.setMag(clo.mag);
            break;
        case "Squall":
            ene1.setName(Names.SQUALL);
            ene1.setHairColor(Stats.BLACK);
            ene1.setWep(Weapons.LIONHEART);
            ene1.setSkill(squ.skill);
            ene1.setAp(squ.ap);
            ene1.setStr(squ.str);
            ene1.setMag(squ.mag);
            break;
        case "Zidane":
            ene1.setName(Names.ZIDANE);
            ene1.setHairColor(Stats.LIGHTBROWN);
            ene1.setWep(Weapons.THIEF_DAGGER);
            ene1.setSkill(zid.skill);
            ene1.setAp(zid.ap);
            ene1.setStr(zid.str);
            ene1.setMag(zid.mag);
            break;
        case "Tidus":           
            ene1.setName(Names.TIDUS);
            ene1.setHairColor(Stats.BLONDE);
            ene1.setWep(Weapons.CALADBOLG);
            ene1.setSkill(tid.skill);
            ene1.setAp(tid.ap);
            ene1.setStr(tid.str);
            ene1.setMag(tid.mag);
            break;
        case "Yuna":
            ene1.setName(Names.YUNA);
            ene1.setHairColor(Stats.DARKBROWN);
            ene1.setWep(Weapons.NIRVANA);
            ene1.setSkill(yun.skill);
            ene1.setAp(yun.ap);
            ene1.setStr(yun.str);
            ene1.setMag(yun.mag);
            break;
        default:
            System.out.println("You did not enter a valid character name");
            break;


        } 
        System.out.println("You have chosen to face " + ene1.name);
        System.out.println("Enemy Skill = " + ene1.skill + " Enemy Weapon = " + ene1.wep);



        System.out.println("Enemy Skill = " + ene1.skill + " Enemy Weapon = " + ene1.wep);

        int eneTotal = ene1.skill + ene1.ap + ene1.str + ene1.mag;

        Stats player = new ThePlayer();

        String plN = GetInput.getInput("What is your name?");
        player.playerName = plN;        
        System.out.println("So Your name is " + player.playerName);

        String plWep = GetInput.getInput("What is your Weapon's name?");
        player.playerWep = plWep;
        System.out.println("So your Weapon is " + player.playerWep);

        Random generator = new Random();
        int plSkill = generator.nextInt(10);
        player.skill = plSkill;
        System.out.println("Your skill level is " + player.skill);

        Random gn = new Random();
        int plAp = gn.nextInt(10 - 5) + 5;
        System.out.println("So your Attack Power is " + plAp);
        player.ap =  plAp;

        Random gns = new Random();
        int plStr = gns.nextInt(10);
        System.out.println("So your Strength is " + plStr);
        plStr = player.str;

        Random gnm = new Random();
        int plMag = gnm.nextInt(10 - 5) + 5;
        player.mag = plMag;
        System.out.println("So your Magic is " + player.mag);


        int plHax = 15;
        double doubleResult = plHax;


        double ene1Hax = 3.99;
        int intResult = (int)ene1Hax;


        double doubleValue = 6.99;
        Double doubleObj = new Double(doubleValue);
        int intR = doubleObj.intValue();

        System.out.println(intR);

        int plyrTotal = player.skill + player.ap + player.str + player.mag;

        if (plyrTotal > eneTotal) {
            System.out.println("Congratulations you beat " + ene1.name + " Please Play Again!" );

        } else if (plyrTotal == eneTotal) {
            System.out.println("You drew with " + ene1.name + " Play again and Win!");
        }
        else
        {
            System.out.println("You were not succesful this time " + ene1.name + " Defeated you by " + (eneTotal - plyrTotal) + " Please Try Again");

        }


    }

}

在这之后,我有更多代码为玩家“统计数据”和角色生成随机数,然后匹配他们统计数据的总值以确定“获胜者”,我想将其放入单独的班级。我的问题是,

如何使用 Main 类的 switch 语句中输入的值在单独的类中获取 ene1。

为了清楚起见,更新为完整的主要方法

【问题讨论】:

  • 我会使用 IDE 中的重构来选择要提取到另一种方法中的代码。然后我会将方法移动到另一个类(再次使用您的 IDE)

标签: java class methods instance


【解决方案1】:

您遇到的一个问题是您将 Enemy 指定为 Stats 的子类,但与您的角色无关。因此,虽然敌人具有与角色相同的属性,但它与角色没有关系。与其复制名称和颜色等所有这些值,不如让 Enemy 成为拥有 Stats 值的自己的实体,与 stats 共享接口。然后敌人可以使用该接口调用 Stats 类中的各种方法。

public class Static implements Actions{
    // ...
}

public class Enemy implements Actions{
   private Static characterType;
}

为了将来参考,您能否将您的问题设计得更通用?它不仅可以帮助那些不了解参考的人,还可以让有类似问题的人更容易找到它。

【讨论】:

    【解决方案2】:

    您可以将它传递给该类的方法(或构造函数),就像传递任何其他变量或文本一样。即

     clo.setOpponent(ene1);
    

    那么让setOpponent的实现是这样的

     class Stats
     {
          private Stats opponent;
          //ALL OF YOUR OTHER CODE AND METHODS GO HERE
    
          public void setOpponent(Stats enemy)
          {
              opponent = enemy;
          }
     }
    

    这并没有考虑到您的应用程序糟糕的 OO 设计,它只回答了您的问题。更好的设计需要更多的实践和一些学习(查找 IS-A 和 HAS-A 关系以帮助基本 OO 设计)

    【讨论】:

    • 那么我应该如何设计它以使其对 OO 更友好?不会假装是专家(甚至接近),大约一个月前的一个晚上,我才真正开始学习 java 一个小时左右
    • @FinalFind Zylth 的回答涵盖了一个很好的方法,但考虑到您不仅对 OO 而且对一般编程都很陌生,这可能会让人感到困惑。我无法在评论中教你 OO,但请查看这个问题+答案以了解开始的地方:stackoverflow.com/questions/2218937/…
    • 是的,你不能,但如果你有时间,你能告诉我你会怎么做吗?查看您帖子上的链接,我没有充分考虑 IS-A 和 HAS-A。有我坐在认为我已经做了一个半体面的 Java 应用程序 =P
    • 这不会将我的代码全部保存在一个类中,因为我的代码确实在其当前状态下工作,我觉得执行全部在一个大型 Main 类中是错误的(如在OP)
    • @FinalFind 您不希望所有代码都在一个类中执行。你想做几件事——你想分解代码。您不仅想将其分解,而且还想将其放入有意义的现实生活中。每个类都应该有一个目的(单一职责原则)。这将有助于防止代码重复。因此,您拥有以特定战士命名的所有这些类。这些应该是实例名称而不是类。所有这些类有什么共同点?一切。姓名、发色等所以从 OOD 的角度来看,它们都可以是同一个类
    【解决方案3】:

    在您的特定示例中,我建议对敌人使用枚举,而不是使用类层次结构,因为您对所有敌人实体都有相同的字段,并且您在这里没有使用任何外部存储(如数据库、文件或随便)。

    类层次结构更适合以下情况:当您有多个具有相似性和区别性的实体时。例如,您可以为普通敌人设置一个等级,为具有某些超级技能的“强制”敌人设置一个等级,因此第二个等级将继承第一个等级并具有 1 个附加字段。这使您可以减少代码重复并提供足够的灵活性。此外,当您希望将此实体保存在某些存储(例如 DB)中时,类层次结构为您提供了更多好处。

    但在您的情况下,使用单个 Enum 来拥有一组敌人更为合乎逻辑,这些敌人是“硬编码”到应用程序中的。我建议下一个解决方案:

    public enum Enemy {
        CLOUD("Cloud", "Red", "Sword", 10),
        SQUALL("Cloud", "Black", "Minigun", 999)
        // and so on
        ;
    
        public String name;
        public String hairColor;
        public String wep;
        public int skill;
    
        Enemy(String name, String hairColor, String wep, int skill /* and so on */) {
            this.name = name;
            this.hairColor = hairColor;
            this.wep = wep;
            this.skill = skill;
        }
    
        public static Enemy getByName(String name) {
            for (Enemy enemy : Enemy.values()) {
                if (enemy.name.equalsIgnoreCase(name)) {
                    return enemy;
                }
            }
            throw new IllegalArgumentException("Enemy with the name `" + name + "` doesn't exist.");
        }
    }
    

    然后就可以在主类中通过键名来初始化一个敌人:

    String versus = GetInput.getInput("\nWhich of these Characters would you like to go up against?");
    try {
        Enemy enemy = Enemy.getByName(versus);
    } catch (IllegalArgumentException e) {  // processing incorrect input
        System.out.println(e.getMessage());
    }
    

    然后你可以将此常量传递给任何其他类来处理它并计算你想要的任何东西:

    public class FightCalculator {
        public int calculateScore(Enemy enemy) {
             // Some calculations here...
        }
    }
    

    【讨论】:

    • 嘿,我实际上有一个枚举,其中包含名称。我没有意识到你可以将它们用于除了作为字符串调用之外的任何东西
    • 公共枚举名称 { CLOUD("Cloud"), SQUALL("Squall"), ZIDANE("Zidane"), TIDUS("Tidus"), YUNA("Yuna");私有字符串名称AsString;私有名称(字符串 nameAsString){ this.nameAsString = nameAsString; } @Override public String toString() { return this.nameAsString; } }
    • 使用枚举来存储名称也可能是一个不错的解决方案,但似乎在您的情况下,您可以在每个枚举项中拥有更多数据 :) 您仍然可以使用 Wea​​pons 和 Stats 枚举作为 Enemy 枚举中的字段。
    • 所以你说要完全删除所有字符类,即 Cloud、Squall 等(看起来像这样)import com.George.revision.Characters; import com.George.revision.Weapons; public class Squall extends Stats { public Squall() { setLionheart(7); this.hairColor = Stats.BLACK; this.name = Characters.SQUALL; this.wep = Weapons.LIONHEART; this.skill = 7; this.ap = getLionheart(); this.mag = 4; this.str = 8; } } 并将它们放入单个 Enum 中?
    • 或者你是说只为敌人制作这个枚举?
    【解决方案4】:

    创建单独的 HeroEnemy 类可能会有所帮助。或者,如果你的角色不是“好”或“坏”的人,也许只是一个Character 类。对于下面的讨论,我将简单地使用Character,但是您可以将其替换为HeroEnemy,它应该仍然有意义。

    首先,CharacterStats 是什么关系。我认为Characater 有一个 Stats。这意味着Character 应该有一个Stats 类型的成员变量:

    class Character {
        private Stats stats = new Stats();
    }
    

    现在您可以为Character 添加一个新的Stats 对象的构造函数。这意味着Character 需要为Stats 中存储的每个值获取多个参数。这种方法的一个优点是您只需编写一次代码来设置 Stats 对象,然后每个 case 语句只有 1 行:

    ene1 = new Character(/* all the stats values go here */);
    

    这里的故事的寓意是,当您发现自己重复代码时,您应该考虑编写一个封装该重复的方法。

    【讨论】:

      猜你喜欢
      • 2023-02-09
      • 2010-10-13
      • 1970-01-01
      • 2011-03-26
      • 2012-10-22
      • 2011-01-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多