Применение в другом классе переменной в C#
У меня есть класс простой Player:
// Класс игрока
public class Player
{
private string _name;
}
Также, например, хочу сделать класс Enemy, в котором хочу применить переменную _name(Только в этом классе). Вопрос, мне надо в классе Enemy наследоваться от Player или есть другое решение?
Дополнение: Например, у нас есть класс "монетка" и когда игрок подбирает монетку, то в классе "монетка" вызывается метод, который выводит следующее - "Игрок {_name (Из класса Player) подобрал монетку}". Как это реализовать максимально правивльно?
Ответы (3 шт):
Не совсем понятны конкретные мотивы этого. Если поле _name должно быть во всех классах-сущностях, описывающих персонажей, то есть смысл определить вот таких образом:
public class Player
{
protected string Name { get; set; }
}
public class Enemy : Player
{
//здесь будет доступно поле Name
}
Если вы имели в виду что-то другое, то сформулируйте задачу чуть более конкретно в комментарии.
Проектирование классов ООП строится на простых логических цепочках.
Спросите себя, может ли враг Enemy быть прямым наследником игрока Player? Игрок Player в теории должен управлять игроком, взаимодействовать с другими игроками, быть хорошим и иметь другие характеристики. Класс Enemy как по мне всем этим не обладает, к тому же изменения Player могут отразиться на Enemy, поэтому тут ошибка логического проектирования.
После лирического отступления, напрямую к способам.
Можно просто задублировать, ведь логически это разные сущности.
В этом в принципе нет ничего плохого, ведь лучше задублировать сейчас, чем в будущем при переписывании страдать от собственного наследования и разделять эти сущности.
public class Player
{
private string _name;
}
public class Enemy
{
private string _name;
}
Можно выделить общего родителя, чтобы сохранить логику.
Однако учтите, что наследоваться можно только от одного класса. Обратите внимания на измененный модификатор доступа на protected.
public class Character
{
protected string _name;
}
public class Player : Character
{
}
public class Enemy : Character
{
}
Можно избавляться от зависимостей с помощью интерфейсов.
В основном это нужно для того, чтобы обработка в методах шла одинаковым образом.
public interface ICharacter
{
string name { get; set; }
}
public class Player : ICharacter
{
public string name { get; set; }
}
public class Enemy : ICharacter
{
public string name { get; set; }
}
Тогда можно обрабатывать сущности так:
List<ICharacter> list = new List<ICharacter>()
{
new Player(), new Enemy()
}
foreach(ICharacter character in list)
Console.WriteLine(character.name);
Есть еще всякие паттерны проектирования, но это уже другая история.
public class Player
{
public string name { get; set; }
}
public class Enemy
{
private Player player;
public string name { get; set; }
public Enemy(Player player) { this.player = player; }
public void Attack()
{
Console.WriteLine($"Враг {this.name} была атакован игроком {player.name}");
}
}
P.S. Судя по описанию, общий родительский класс вполне подойдет.
public abstract class Unit {
public string Name { get; protected set; } // Можно запросить, но нельзя изменить из вне Unit и его наследников
protected UnitControl control; // Доступно только для Unit и его наследников
// Дольнейшие общие переменные
public abstract void Dead (); // Функция не реализована, но обязательна для реализации у наследников
// Дольнейший общий функционал
}
public class Player : Unit {
public Player () {
Name = "Hero";
control = new PlayerControl();
}
public override void Dead () {
// GameOver
}
}
public class Enemy : Unit {
public Enemy () {
Name = "Monster";
control = new EnemyControl();
}
public override void Dead () {
// Drop Loot
}
}
public class Test {
public Test () {
Enemy NewEnemy = enw Enemy();
Console.WriteLine(NewEnemy.Name); // можно
NewEnemy.Name = "Gollum"; // нельзя
}
}
Name публичная переменная. get позволяет обратиться к ней кому угодно, а protected set позволит задавать это поле только самому Unit и тем, кто от него наследуется, защищая от внешнего редактирования.
Если Enemy, родственный классу Player, то не Enemy наследуется от Player, а они оба наследуются от некого общего Unit. abstract значит, что Unit не может быть создан сам по себе (new Unit()), он как болванка описывающая функции.
А вообще вам бы почитать про наследование. Узнаете много интересного, чем будете пользоваться всегда и везде.