Я пытаюсь хранить объекты, которые являются только подклассом абстрактного класса. Однако я могу видеть только методы абстрактного класса и ни один из методов подкласса. Что я пропустил?
Класс с ошибкой в:
class CharacterStats
{
private Dictionary<StatType, Stat> playerStats;
//Contructor for new game
public CharacterStats()
{
playerStats = new Dictionary<StatType, Stat>();
//Creates all Stats with default values
playerStats.Add(StatType.STA, new StatSta());
playerStats.Add(StatType.STR, new StatStr());
playerStats.Add(StatType.DEX, new StatDex());
playerStats.Add(StatType.DEF, new StatDef());
}
//Returns the damage reduction in %
public int GetDamageReduction()
{
playerStats[StatType.DEF]. //Missing Methods from StatDef class
//Added to remove error message
return 1;
}
}
Абстрактный класс:
abstract class Stat
{
protected int pointsAdded;
protected int pointCap;
public Stat() {}
public string TestMethod()
{
return "Working!";
}
}
Подкласс:
class StatDef : Stat
{
public StatDef() : base()
{
this.pointsAdded = 0;
this.pointCap = 100;
}
public int ApplyDamageReduction(int dmg)
{
//removed data to read easier
return 1;
}
}
Спасибо
@ Дай, это должен быть ответ
Тип экспрессии playerStats[StatType.DEF]
- это просто Stat
. Компилятор не знает, какой тип Stat
хранится там в качестве значения.
Если всегда будет StatDef
, вам нужно просто выполнить приведение:
var def = (StatDef) playerStats[StatType.DEF];
// Now you can use def.ApplyDamageReduction etc
Однако вам нужно будет использовать любой, когда вы хотите использовать член, зависящий от статистики. Если вы часто не хотите обрабатывать несколько статистических данных одинаково, я бы предложил отказаться от словарного подхода и просто использовать отдельные поля:
class CharacterStats
{
private StatDefence defence;
private StatAttack attack;
private StatStrength strength;
// etc
}
Вы можете легко написать метод, который позволяет вам перебирать всю статистику для тех случаев, когда этот является полезен:
public IReadOnlyList<Stat> GetAllStats() =>
new Stat[] { defence, attack, strength, ... };
Но я подозреваю, что наиболее, когда вы используете статистику, вы действительно хотите знать конкретную статистику. Я всегда лучше напишу:
var strength = stats.Attack;
чем
var strength = stats[StatType.STR];
даже если при не мне нужны конкретные аспекты статистики прочности.
Я планировал вычислить несколько разных значений в каждой статистике, таких как уменьшение урона, а также сохранить количество очков в каждом и общее допустимое количество очков. Возможно ли, чтобы значение словаря было подклассом, поскольку это работало бы очень хорошо, если бы я мог сделать это или что-то подобное. Еще одна причина, по которой я хотел использовать словарь, заключалась в том, что в будущем я собирался включить больше статистики и подумал, что это хороший способ сгруппировать все эти объекты.
@HamishKendall: значение уже является ссылкой на экземпляр подкласса. Но вы не должны ожидать, что тип во время компиляции результата поиска в словаре будет «типом, который вы хотите, чтобы он был» - это тип, который вы указали как второй аргумент типа для Dictionary<,>
. Да, вы, безусловно, можете иметь общность в своем абстрактном базовом классе, но я все еще не уверен, что словарь - лучший способ приблизиться к этому. У вас есть определенный набор ключей, и вы знаете тип результата для каждого ключа, поэтому для меня это больше похоже на набор полей.
Ваш словарь набирается на
Stat
, а не на подкласс. Компилятор не знает, каким может быть фактический подкласс во время выполнения, поэтому вы должны сначала преобразовать его в подкласс самостоятельно - при условии, что вы знаете, что это за подкласс.