Java:从2个不同的类传递2个对象并访问它们的所有变量

时间:2018-07-19 16:22:43

标签: java

我只想创建一个简单的程序来教我如何正确地将对象从不同的类传递到函数。我有2个类别,玩家和敌人,每个类别都有1个变量“速度”,然后有一个战役类别,接受这两个对象,然后确定付款人是否更快,但是我不确定如何访问我传递的对象的变量

播放器类

public class Player {

   int speed = 0;

   public Player(){
       setSpeed(5);
   }

   public void setSpeed(int speed) {
       this.speed = speed;
       }
   }

敌人阶级

public class Enemy {

   int speed = 0;

   public Enemy(){
       setSpeed(3);
   }

   public void setSpeed(int speed) {
       this.speed = speed;
       }
   }

战斗课

public class Battle {

public Battle(Object a, Object b){
    if (faster(a.speed, b.speed)){    //This is where the problem is
        System.out.println("Faster");
    }
    else{
        System.out.println("Slower");
    }

}

Boolean faster(int speed1, int speed2){
    if (speed1 > speed2){
        return true;
    }
    else{
        return false;
    }
}

}

主要班级

public class Main {
   public static void main(String[] args) {
       Player player = new Player();
       Enemy enemy = new Enemy();
       Battle battle = new Battle(player, enemy);

   }

}

2 个答案:

答案 0 :(得分:0)

下面是您的代码的简短版本,但这应该可以实现,您也可以使用两个不同的类来实现。

public class Player {
    private int speed;

       public Player(int speed){
           this.speed=speed;
       }

    public int getSpeed() {
        return speed;
    }

    public void setSpeed(int speed) {
        this.speed = speed;
    }      
}




public class Battle {

    Player player;

    static void battle(Player obj1, Player obj2){
        if (obj1.getSpeed() > obj2.getSpeed()){
            System.out.println("Faster");
        }
        else{
            System.out.println("Slower");
        }
    }


    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Player player1 =new Player(5);

        Player player2 = new Player(3);

        battle(player1,player2);


    }

}

答案 1 :(得分:0)

问题的解决方案

要编译程序,您需要将Battle的构造函数的参数声明为PlayerEnemy,以便Java查找speed字段:

public class Battle {
    public Battle(Player a, Player b) {
        if (faster(a.speed, b.speed)) {
            System.out.println("Faster");
        } else {
            System.out.println("Slower");
        }

    }
    // ...
}

但是,这确实可以防止传入Enemy实例。您可以提供overloaded methods,但是更好的解决方案是使用PlayerEnemy的(probably abstract)基类或interface继承供他们实施。

使用抽象基类

严格地使基类抽象不是必需的,但是它确实阻止了它的实例化,我们只希望允许子类PlayerEnemy实例化。它还强调了该类旨在被子类化,而不是被其自身使用。

// Character.java
public abstract class Character {
    private int speed;

    public Character(int speed) {
        this.speed = speed;
    }

    public int getSpeed() {
        return speed;
    }
}

// Player.java
public class Player extends Character {
    public Player() {
        super(5);
    }
}

// Enemy.java
public class Enemy extends Character {
    public Enemy() {
        super(3);
    }
}

使用此方法,可以修改Battle的构造函数以使其适合:

// ...
    public Battle(Character a, Character b) {
        if (faster(a.getSpeed(), b.getSpeed())) {
            System.out.println("Faster");
        } else {
            System.out.println("Slower");
        }
    }
// ...

使用接口

与(抽象)类相反,接口通常描述实现接口的对象支持的某些动作。

// HasSpeed.java
public interface HasSpeed {
    int getSpeed();  // interface methods are public and abstract by default
}

// Player.java
public class Player implements HasSpeed {
    @Override
    public int getSpeed() {
        return 5;
    }
}

// Enemy.java
public class Enemy implements HasSpeed {
    @Override
    public int getSpeed() {
        return 3;
    }
}

在这里,Battle的构造函数将进行如下修改:

// ...
    public Battle(HasSpeed a, HasSpeed b) {
        if (faster(a.getSpeed(), b.getSpeed())) {
            System.out.println("Faster");
        } else {
            System.out.println("Slower");
        }
    }
// ...

为什么需要这样

您遇到的问题是,您试图访问声明为Player的变量上的EnemyObject类的字段。这将适用于大多数动态类型的语言(例如Python或JavaScript),但不适用于静态类型的语言(例如Java)。

动态键入

在动态类型语言中,将在运行时确定并检查任何变量和/或字段的类型。这意味着无论如何都可以使用大多数这些语言的任何参数传递任何对象。检索该字段的值时,将检查该对象是否具有某个字段。

这种处理方式使最初编写代码稍微容易一些,但是它也增加了丢失错误的可能性,因为这些错误只会在运行时报告,直到它们出现。

作为示例,如果Java是动态类型的,则您的程序将运行良好,直到将PlayerEnemy以外的其他内容传递给Battle的构造函数,并且找不到speed字段。

静态输入

在静态类型语言中,类型及其字段以及方法在编译时进行检查,因此需要在其声明中提供参数和变量的类型。然后只能将这些类型及其子类型分配给它们。这样可以确保该对象具有您期望的所有字段和方法,尽管对于子类型,它可能具有更多的对象。

您已经知道,如果分配了声明类型之外的其他内容,则会在程序编译期间引发错误。可以抑制这些错误,例如通过强制转换,但仍会发出警告。

这虽然有一定的局限性,但可以确保除非采取特殊措施,否则由于缺少字段或方法,绝不会出现运行时错误。这样的错误将始终在编译期间被捕获。

进一步阅读

This article似乎很好地概述了静态和动态类型语言之间的区别。

在上面的示例中,我们对此有一个大概的了解,但是您可能希望研究封装以编写更适合Java约定的代码。我不会在这里讨论这个问题,因为它打破了答案的范围,但是here是一些进一步的信息。

我还发现,对于学习新的编程语言,框架或原理,书籍是很好的资源。尤其是如果您每天都有公共交通工具上下班,这是一种消磨时间并在学习过程中学习知识的绝妙方法。奥赖利(O'Reilly)的《 'Java in a Nutshell'》这本书使我对Java有所了解。我发现它写得不错,但是还有很多其他选择。