Почему обьект вызывающий метод передает в качестве аргумента поле другого обьекта а не свое

class Unit
{
    protected int _health;
    protected int _damage;

    public virtual void Attack(Unit unit)
    {

        unit.TakeDamage(_damage);//почему скелет вызывая метод передает аргументом поле _damage обьекта Archer?.. а не свое поле
    }

    public virtual void TakeDamage(int damage)
    {
        Console.WriteLine(damage);

        if (damage >= _health)
        {
            _health = 0;
            Die();
            return;
        }
        _health -= damage;
    }

    protected virtual void Die() { }
}

class Skeleton : Unit
{
    public Skeleton()
    {
        _health = 15;
        _damage = 12;
    }

    public override void Attack(Unit unit)
    {
        Console.WriteLine("Скелет атакует.");
        base.Attack(unit);
    }

    protected override void Die()
    {
        Console.WriteLine("Скелет убит.");
    }
}

class Archer : Unit
{
    public Archer()
    {
        _health = 50;
        _damage = 15;
    }

    public override void Attack(Unit unit)
    {
        Console.WriteLine("Лучник атакует.");
        base.Attack(unit);
    }

    protected override void Die()
    {
        Console.WriteLine("Лучник убит.");
    }
}

class Program
{
    static void Main(string[] args)
    {
        Archer archer = new Archer();
        Skeleton skelet = new Skeleton();
        archer.Attack(skelet);
        archer.Attack(skelet);
    }
}

Ответы (2 шт):

Автор решения: Tigran Grigoryan

Это зависит не от объекта, а от параметров метода.

В вашем случае создан класс Unit, от которого наследуются Skeleton и Arhcer.

 public override void Attack(Unit unit)
{
    Console.WriteLine("Лучник атакует.");
    base.Attack(unit);
}

В этой части кода в параметрах указан Unit. Это значит что сюда можно ставить класс Unit, либо его классы наследники.

→ Ссылка
Автор решения: Алексей Шиманский

И лучшник и скелет наследуются от Unit. И тот и другой имеют возможность вызвать методы Attack и TakeDamage.

В программировании (во всяком случае C#), если после наименования объета стоИт точка и имя метода, то метод вызвается у него и все свойства внутри этого метода, принадлежат этому объекту. Поэтому если написать car.Drive(), то свойства внутри метода будут от объекта car, а не ещё от какого-либо.

Если представить, что метод Attack не имеет паракметров, то при вызове archer.Attack(); свойство _damage всегда принадлежит к лучнику и никак иначе. Если skelet.Attack();, от свойство _damage всегда принадлежит к скелету и никак иначе. Аналогично с методом TakeDamage.

Еще раз: передаёшь ли ты агрументы в методы или нет, то _damage принадлежит только тому объекту, на котором вызыван метод.

Однако в методе Attack можно передать любой объект, унаследованный от Unit.

и тогда на строчке unit.TakeDamage вызовется метод TakeDamage какого объекта? Правильно, того, что передали как аргумент..То есть можно считать, что если передали skelet, то будет на самом деле не unit.TakeDamage, а skelet.TakeDamage. Если перередали как аргумент archer, то будет не unit.TakeDamage, archer.TakeDamage.

А что мы знаем о том, к чему применяется метод? Что свойства внутри метода будут от объекта, на котором вызвали метод. И получается, что если в качестве unit передали skelet, то это превращается в skelet.TakeDamage(XXX) и получается что у скелета начинает работать этот метод.

→ Ссылка