如何从一个类中访问另一个类的字段?

3

请注意,这不是继承或接口。

我有一个名为 HP 的类。

public class HP
{
    public int Base;

    public int Value
    {
        get
        {
            //Need to access Monster.Level to calculate total HP.
        }
    }
}

有一个类名为Monster,调用了HP方法。

public class Monster
{
    public HP hp;
    public int Level;
}

我如何从HP访问Monster.Level?

我尝试在实例化时通过引用将Level传递给HP

public class HP
{
    private ref int Level;

    public A(ref i)
    {
        Level=i;
    }
}

但我希望保持A尽可能简单和清晰。

我不想在创建时传递等级的原因是Level是一个不断变化的值,每当怪物升级或发生其他变化时,我就必须"更新"HP,这是一种效率低下的做法。

而且还有其他访问Level的内容,比如AttackDamage等。

目前我在HPAttackDamage等中都有一个方法,将Level作为参数。

public int Value(int lv)
{
    return Base+10*lv;
}

但根据我所知道的一点SOLID原则,这是非常糟糕的编码!


3
如果您的问题与继承无关,那么最好不要使用继承相关的术语,例如“子类”和“基类”,这将非常有帮助。 - Damien_The_Unbeliever
4
你可能正在寻找静态成员,或者实际上并不理解类的概念。 - Rafalon
1
既然我们已经澄清了这不是继承,你能告诉我们通过从A访问B.i解决什么问题吗? - Enigmativity
2
@Noob001 在将 B 的实例传递到 A::DoSomething() 或在 A 实例化期间传递到 A 中是否存在任何挑战? - Sisir
我认为HP.Value不应该是只读属性,而应该是一个带有参数level的函数。就这么简单。 - Fildor
显示剩余7条评论
4个回答

2
似乎你所说的HP更像是一个HPCalculator,负责根据怪物等级和可能在未来加入的其他数据计算怪物的生命值。我认为这样的HPCalculator需要访问它所计算的怪物的Monster非常关键。
C#中,类是通过引用而不是值来完成的,这意味着你可以毫不费力地拥有像这样的东西:
public class Monster{
    public HP hp;
}

public class HP{
     public Monster monster;
}

1
这样的解决方案怎么样?
public class HP
{
    private Monster _monster;
   public HP(Monster monster)
    {
        this._monster = monster;
        
    }
    public int Base;

    public int Value
    {
        get
        {
            Console.WriteLine(_monster.Level);
        }
    }
}

那么怪物类可以像这样:

然后怪物类可以像这样

 public class Monster
{
    public HP hp;
    public int Level;
    public Monster(int level)
    {
        this.Level = 10;//can be set to level ,this is for testing.
        hp = new HP(this);
    }
}

这不是一个很好的解决方案,我认为你应该考虑使用继承。


请问您能否友好地向我展示如何通过继承正确地完成它?非常感谢。 - Noob001
我认为@enigmativity刚刚发布了完美的继承解决方案...去看看吧。 - siddharth gupta

1
如果您想避免继承,那么这个应该做您想要的事情:
public class Monster
{
    public int Level { get; set; }
    private MonsterHitPointCalculator _hp = new MonsterHitPointCalculator();
    public int HitPoints => _hp.Compute(this);
}

public class MonsterHitPointCalculator
{
    private int _base = 42;
    public int Compute(Monster actor) => this._base + 10 * actor.Level;
}

但是我认为在你的情况下继承是更好的选择。请尝试使用以下代码:

public abstract class Actor
{
    protected int _base = 42;
    public int Level { get; set; }
    public virtual int HitPoints => _base + this.Level;
}

public class Monster : Actor
{
    public override int HitPoints => _base + 10 * this.Level;
}

public class Human : Actor
{
    public override int HitPoints => base.HitPoints + 20;
}

在这两种情况下,以下代码可以用于获得相同的示例结果:
var monster = new Monster();

monster.Level = 1;
Console.WriteLine(monster.HitPoints);

monster.Level = 2;
Console.WriteLine(monster.HitPoints);

它输出:
52
62

非常感谢您的出色回答!但是我真的不知道如何将其应用到我的代码中!因为实际上,它要复杂得多!如果可能的话,我希望它可以在 HP 类或 AttackDamage 类中进行计算。非常感谢。 - Noob001
@Noob001 - 我建议你现在提出第二个问题,并包含更多的细节和其他类。不要只编辑这个问题 - 最好新建一个问题。 - Enigmativity

0

你必须学习解释类的教程。理解这个概念非常重要。但是根据我所知道的一点SOLID原则,这是非常糟糕的编码!在理解类、结构体、属性、接口、多态的概念并获得这些东西的工作方式的一般知识之后,再去学习SOLID原则。现在先忘记SOLID原则,几个月后再去学习。

让我向你展示如何正确地编写代码:

首先,你不应该使用自己的类来表示HP。除非你知道自己在做什么并且有充分的理由,否则这没有任何意义。保持简单:

public class Monster
{
    public int HP;
    public int MaxHP;
    public int Level;
}

你刚刚尝试将HP包装成自己的类,但它基本上只是一个整数。

回答你关于如何使用它的问题:
这是一个包含一些单位信息的类:

public class UnitStats
{
    public int HP;
    public int Energy;
    public int Level;
}

现在,就您的单元类而言:

public class Monster
{
    public UnitStats Stats;
    public string Name;

    public void Setup (int hp, int level, string name)
    {
        Stats = new UnitStats (); // Create an instance/object of the class.
        Stats.MaxHP = hp; // Set its values.
        Stats.HP = hp;
        Stats.Level = level;
        Name = name;
    }
}

提示:不要为每个单元使用自己的类。找到一个通用类,在其中可以定义每个单元。
提示2:我故意没有使用属性。但通常情况下,您永远不会使用公共字段,只使用公共属性。在Unity中,您使用公共字段将它们暴露在检查器中,这是我知道的唯一有效的情况。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接