Можно ли заменить два метода одним?
Есть класс, содержащий два свойства, HP и Armor, и два метода, SetHP() и SetArmor(). Оба метода работают по одному алгоритму, но метод SetHP() устанавливает значение свойства HP, а SetArmor() - значение Armor. Чувствуется повторяемость кода, можно ли заменить методы одним универсальным?
public virtual int HP
{
get => Settings[Setting.HP];
private set => Settings[Setting.HP] = value;
}
public virtual int Armor
{
get => Settings[Setting.Armor];
private set => Settings[Setting.Armor] = value;
}
public virtual void SetHP(int newHP, int striker, int delta = 0)
{
int oldHP = HP;
HP = newHP;
if (delta == 0)
{
delta = oldHP - HP;
}
Event(Message.HPChanged, this, delta, striker, Settings[Setting.HP]);
}
public virtual void SetArmor(int newArmor, int striker, int delta = 0)
{
int oldArmor = Armor;
Armor = newArmor;
if (delta == 0)
{
delta = oldArmor - Armor;
}
Event(Message.ArmorChanged, this, delta, striker, Settings[Setting.Armor]);
}
}
Ответы (1 шт):
Предлагаю чуток переделать вашу реализацию. Создать базовый класс Entity, от которого будут наследоваться дочерние. Пример реализации класса:
internal abstract class BaseEntity : INotifyPropertyChanged, IDisposable
{
private string _name;
private double _hp;
private double _armor;
public event PropertyChangedEventHandler PropertyChanged;
public string Name
{
get => _name;
private set
{
_name = value;
OnPropertyChanged(nameof(Name));
}
}
public double HP
{
get => _hp;
private set
{
_hp = value;
OnPropertyChanged(nameof(HP));
}
}
public double Armor
{
get => _armor;
private set
{
_armor = value;
OnPropertyChanged(nameof(Armor));
}
}
public BaseEntity(string name, double hp, double armor)
{
Name = name;
HP = hp;
Armor = armor;
}
protected virtual void SetHP(double hp) => HP = hp;
protected virtual void SetArmor(double armor) => Armor = armor;
public void Dispose()
{
Name = default;
HP = default;
Armor = default;
}
private void OnPropertyChanged(string propertyName) =>
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
Затем создаёте дочерний класс. Пусть, например, это будет класс с игроком:
internal class Player : BaseEntity
{
public Weapon Weapon { get; private set; }
//просто пример некоего класса (Weapon), который описывал-бы оружие, которое есть у игрока
public Player(string name, double hp, double armor, Weapon weapon) : base(name, hp, armor)
{
Weapon = weapon;
}
public void Hit(double damage)
{
if (Armor > 0)
{
SetHP(HP - (damage / 4));
SetArmor(Armor - (damage / 2));
}
SetHP(HP - damage);
}
}
Для подписки на событие PropertyChanged используйте следующее:
var player = new Player(default, default, default, default);
player.PropertyChanged += Player_PropertyChanged;
private void Player_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
throw new NotImplementedException();
}
По аналогии можете создать для кошечек, для собачек и прочих npc, которые есть в вашей игре (если это игра).
Есть ещё другой вариант: в BaseEntity создаёте виртуальный метод урона, в котором пишите всю основную логику. В дочерних классах переопределяете данную логику под ваши нужды