@Anther
Начинающий

Как сделать иерархию классов?

А если быть точным. Как сделать иерархию классов так, чтобы к ним можно было обращаться как с общими. Сейчас поясню.
Например, у нас есть такая иерархия: Враг -> Слизень. У класса Врага есть свойство Имя, а у класса Слизень, который наследуется от класса Враг, есть и свойство Имя, и свойство Здоровья. Так же есть отдельный класс Война с методом Битва. В метод Битва передаётся тип Враг, но у класса Враг нет свойства Здоровья. В этом и заключается мой вопрос. Как создать иерархию так, чтобы с экземплярами можно было обращаться как с общими?
Желательно без костылей и подробно, зарание спасибо.

Вот код:
class Program
    {
        static void Main()
        {
            var AnotherSlug = new Slug("common slug", 10);

            War.Battle(AnotherSlug);
        }
    }

    class War
    {
        static public void Battle(Enemy e)
        {
            Console.WriteLine(e.Name); // Нет ошибки 
            Console.WriteLine(e.HP);   // Есть ошибка
        }
    }

    class Enemy
    {
        public string Name { get; set; }

        public Enemy(string name)
        {
            Name = name;
        }
    }

    class Slug : Enemy
    {
        public int HP { get; set; }

        public Slug(string name, int hp) : base(name)
        {
            HP = hp;
        }
    }
  • Вопрос задан
  • 647 просмотров
Решения вопроса 1
@majstar_Zubr
C++, C#, gamedev
Поднимите свойство в класс-родитель.
Сделайте виртуальные методы в родителе bool Damage( int damagPoints ), bool Heal (int healthPoints).

Зафиксируйте инварианты в родителе: отрицательного здоровья не может быть, отрицательный урон наносить нельзя, отрицательные лечение делать нельзя, выше максимального передела шакала здоровья быть не может.

Если хотите сделать некоторых конкретных Enemy с особыми свойствами, то сделайте реализации инвариантов также виртуальными. Допустим Slug получает 50% урона и только чётный урон.

Тогда например Slug:

new public bool Damage( int damagePoints )
{
    if (isDamageAcceptable(damagePoints))
    {
        int appliedDamage = Math.Ceiling(damagePoints/2);
        TakeDamage(appliedDamage);
    }
    return isDamageAcceptable(damagePoints);
}

 new protected bool isDamageAcceptable( int damagePoints) => (damagePoints > 0) && (0==damagePoints%2) );


Обобщение есть согласие наследника наследовать И интерфейс И функциональность. Инвариант может расширяться, если он сужается, то это значит, что наследование не подходит для данного класса.

В вашем примере вопрос не имеет смысла, так как нет наследования иерархии функциональности. У вас просто какие-то поля с автогенерацией бесполезных методов для чтения и записи полей.

Если речь о том, что у не у всех задуманных Enemy может быть здоровье, то вам нужно либо менять модель отношения классов и пересмотреть абстракции, либо использовать композицию вместо наследования.
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 1
tsarevfs
@tsarevfs
C++ developer
Почему бы не перенести HP в класс Enemy?
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы