公共字段的替代方案有哪些?

2022-09-04 05:05:33

我正在用java编写游戏,正如问题标题所建议的那样,我正在我的课程中使用公共字段。(暂时)

从我所看到的,公共领域是坏的,我有一些理解为什么。(但如果有人能澄清为什么你不应该使用它们,那将不胜感激)

问题是,从我所看到的(这似乎是合乎逻辑的)是,使用私有字段,但使用getter和setter来访问它们也不好,因为它首先击败了使用私有字段的观点。

所以,我的问题是,有哪些替代方案?还是我真的必须使用带有getter和setters的私人字段?

作为参考,这是我的一个类,以及它的一些方法。

如果需要,我将详细阐述。

public double health;
//The player's fields.
public String name;
public double goldCount;
public double maxWeight;
public double currentWeight;
public double maxBackPckSlts;
public double usedBackPckSlts; // The current back pack slots in use
public double maxHealth; // Maximum amount of health
public ArrayList<String> backPack = new ArrayList<String>();

//This method happens when ever the player dynamically takes damage(i.e. when it is not scripted for the player to take damage.
//Parameters will be added to make it dynamic so the player can take any spread of damage.
public void beDamaged(double damage)
{
    this.health -= damage;
    if (this.health < 0)
    {
        this.health = 0;
    }
}

编辑:出于检查目的,这是我的类现在的样子:(代码示例由于某种原因不起作用,所以它看起来不正确。Weapon

private final double DAMAGE;
private final double SPEED;

public Weapon(double initialDmg,double initialSpd,String startName,double initialWg)
{
    DAMAGE = initialDmg;
    SPEED = initialSpd;
    setItemName(startName);
    setItemWeight(initialWg);
}

public double getSpeed() 
{
    return SPEED;
}


public double getDamage()
{
    return DAMAGE;
}

如您所见,由于 和 不需要更改,因此它们暂时可以是最终的。(如果在游戏的后面,我决定这些值可以“升级”,那么我可能会添加二传手,然后进行验证,或者只是用升级的值制作一把新武器)它们在构造函数中设置。Weapon'sDAMAGESPEEDWeapon's

结论:getters和setters都很好,只要它们被巧妙地使用,并且只在需要时使用。(但是)


答案 1

通常使用 getter 和 setter,而不是向其他对象授予直接更改字段的权限。当您看到99.99%的getter和setter除了直接访问字段之外,什么都不做时,这可能没有任何意义。但是,当你决定当玩家的伤害超过一点时,他会掉落一半的物品栏时,会发生什么呢?或者你想限制魔法物品可以使用多少个背包插槽?您要么必须查找代码中修改字段的所有位置,要么,如果您使用了 getter 和 setter,则完全在类中进行更改。这就是面向对象编程的核心 - 你已经封装了对象在对象本身中做什么的“知识”,而不是将其分散在与该对象交互的所有对象中。


答案 2

面向对象编程的核心概念之一是封装,即从外部隐藏对象的状态(例如,对象中的数据),并让对象处理它自己的状态。

当封装做得好时,对象的状态只能通过对象提供的接口(例如对象具有的方法)从外部世界受到影响。

我认为你的代码已经开始使用封装。

让我们来看看代码

让我们来看看方法。beDamaged

public void beDamaged(double damage)
{
    this.health -= damage;

    if (this.health < 0)
    {
        this.health = 0;
    }
}

在这里我们可以看到,这种方法会被外界调用,玩家的生命值也会受到影响。它还包含逻辑,因此运行状况不能为负数。您编写的播放器方法是将对象的状态保存在您定义为有效状态的参数内。beDamaged

让我们推断一些关于玩家的事情

现在,从上面,我想我可以推断出关于播放器对象的以下内容:

玩家的不能是负数。health

我们推断的总是正确的吗?

让我们看看从您提供的代码中是否始终可以做到这一点。

啊哈!我们在这里有一个小问题:

public double health;

在场存在的情况下,外部世界可以直接操纵场,以便通过如下所示的一些代码将玩家对象的状态放入可能不需要的状态:healthpublic

Player player = new Player();
player.health = -100

我猜玩家不应该处于负数的状态。health

我们能做些什么呢?

这怎么能避免呢?-- 通过拥有字段 。healthprivate

现在,影响玩家健康的唯一方法是通过和方法,这可能是外部世界影响玩家健康的正确方法。healthbeDamagedgainHealth

这也意味着 - 当你创建一个字段时,这并不意味着你应该为该字段创建getter和setter。private

私有字段不需要 getter 和 setter

Getters 和 setter 通常是直接影响对象具有的字段的一种方式,也许需要进行一些验证以防止错误输入使对象具有不应具有的状态,但有时对象本身应该负责影响数据,而不是外部实体。