Perhatikan bahwa ini bukan warisan atau antarmuka.

Saya memiliki kelas HP

public class HP
{
    public int Base;

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

Dan kelas Monster memanggil HP

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

Bagaimana cara mengakses Monster.Level dari HP?

Saya mencoba meneruskan Level dengan merujuk ke HP setelah membuat instance.

public class HP
{
    private ref int Level;

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

Tapi saya ingin menjaga A sesederhana dan sebersih mungkin.

Alasan saya tidak ingin melewati level saat pembuatan adalah Level adalah nilai yang terus berubah, saya kemudian harus "memperbarui" HP setiap kali monster naik level atau sesuatu , yang BUKAN cara yang efisien untuk melakukan sesuatu.

Dan ada hal lain yang mengakses Level, seperti Attack dan Damage, dll.

Saat ini saya memiliki metode dalam HP, Attack, Damage, dll., dengan menggunakan Level sebagai parameter.

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

Tetapi menurut sedikit prinsip SOLID yang saya tahu, ini adalah pengkodean yang SANGAT BURUK!

c#
3
Noob001 18 Mei 2021, 10:19

5 jawaban

Jawaban Terbaik

Jika Anda mencoba menghindari warisan, maka ini harus melakukan hal yang Anda inginkan:

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;
}

Tapi, saya pikir, dalam kasus Anda, warisan adalah jalan yang harus ditempuh. Coba ini sebagai gantinya:

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;
}

Dalam kedua kasus, kode berikut dapat digunakan untuk mendapatkan hasil contoh yang sama:

var monster = new Monster();

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

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

Ini menghasilkan:

52
62
1
Enigmativity 18 Mei 2021, 07:58

Jika Anda ingin melakukannya melalui warisan, Anda dapat melakukannya seperti ini:

public class HP : Monster

Titik dua menunjukkan warisan dari kelas lain

-1
Piyush Raj 18 Mei 2021, 08:00

Anda harus melihat tutorial yang menjelaskan kelas. Sangat penting bagi Anda untuk memahami konsepnya. But according to the a little bit of SOLID principle I know, this is a VERY BAD coding! SOLID muncul setelah Anda memahami konsep seputar kelas, struct, properti, antarmuka, polimorfisme, dan memperoleh pengetahuan umum tentang hal-hal ini dan cara kerjanya. Lupakan SOLID untuk saat ini, ambil lagi setelah beberapa bulan belajar.

Mari saya tunjukkan cara melakukan kode dengan benar:

Pertama-tama, Anda tidak menggunakan kelas sendiri untuk HP. Itu tidak masuk akal kecuali Anda tahu apa yang Anda lakukan dan memiliki alasan yang bagus. Tetap sederhana:

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

Anda baru saja mencoba membungkus HP ke dalam kelasnya sendiri, dan pada dasarnya itu hanyalah bilangan bulat.

Untuk menjawab pertanyaan Anda tentang cara menggunakannya:
Ini adalah kelas yang berisi beberapa informasi unit:

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

Sekarang, pada kelas unit Anda:

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;
    }
}

Petunjuk: Jangan gunakan kelas sendiri untuk setiap unit. Temukan kelas umum di mana Anda dapat mendefinisikan setiap unit.
Petunjuk 2: Saya sengaja tidak menggunakan properti. Tetapi biasanya Anda tidak pernah menggunakan bidang publik, hanya properti publik. Di Unity Anda menggunakan bidang publik untuk mengeksposnya di inspektur, ini adalah satu-satunya kasus valid yang saya ketahui.

0
Battle 18 Mei 2021, 08:29

Bagaimana dengan solusi seperti ini?

public class HP
{
    private Monster _monster;
   public HP(Monster monster)
    {
        this._monster = monster;
        
    }
    public int Base;

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

Maka kelas monster bisa seperti ini

 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);
    }
}

Ini bukan solusi yang sangat baik, Anda harus benar-benar mempertimbangkan untuk menggunakan warisan imo.

1
siddharth gupta 18 Mei 2021, 07:48

Sepertinya apa yang Anda sebut HP lebih merupakan HPCalculator yang bertanggung jawab untuk menghitung HP Monster berdasarkan level Moster ini dan mungkin data lain di masa depan, saya pikir ini tampaknya penting untuk HPCalculator untuk memiliki akses ke Monster yang kesehatannya dihitung.

Di C# kelas dilakukan dengan referensi bukan dengan nilai yang berarti Anda tidak dapat memiliki masalah seperti ini:

public class Monster{
    public HP hp;
}

public class HP{
     public Monster monster;
}
2
Mwarw 18 Mei 2021, 07:44