2015-06-15 4 views
0

Я, наконец, продолжил изучение принципов ООП, и сейчас я делаю простую игру. Вот ситуация: У меня есть один абстрактный класс под названием Элементы, которые содержат все возможные атрибуты элемента как свойства и качество этого пункта как перечисление:C# Сделать свойства видимыми, если условие выполнено

public enum ItemQuality 
{ 
    Common, 
    Uncommon, 
    Rare, 
    Epic, 
    Legendary 
} 

public abstract class Items 
{ 
    public ItemQuality ItemQuality { get; set; } 
    public int Stamina { get; set; } 
    public int Strength { get; set; } 
    public int Agility { get; set; } 
    public int Intelligence { get; set; } 
    public int Damage { get; set; } 
    public int Block { get; set; } 
    public int Armor { get; set; } 
} 

Я еще два класса под названием Оружия и Armor (они наследуют класс Items), и они содержат WeaponType и ArmorType соответственно, оба из которых также перечислены.

Рассмотрите следующую ситуацию: Я создаю новое оружие типа Sword, я могу дать ему значение для Blocking, но это оружие, которое он не может заблокировать. Я хочу, чтобы различные свойства были видны в зависимости от типа Оружие/Броня.

Weapon weapon = new Weapon(); 
weapon.WeaponType = WeaponType.Sword; 
weapon.Block = 5; 

В этом случае я не смог бы увидеть свойство Block.

Чтобы идти еще дальше, я не хочу создавать экземпляры оружия и доспехов отдельно от персонажа (у меня также есть класс символов).

Моя конечная цель сделать что-то вроде этого:

Character character = new Character(); 
character.WeaponType = WeaponType.Sword; 
character.WeaponType.Damage = 10; 

Или что-то вроде этого, я даже не уверен, что моя структура является правильным, так что я открыт для предложений! Спасибо!

+6

Рассмотрите возможность использования интерфейсов вместо этого и используйте композицию вместо наследования. –

+0

Возможно, узор декоратора может быть чем-то для вас. Таким образом, вы можете обернуть базовый класс декоратором, содержащим дополнительные свойства – LInsoDeTeh

+0

Спасибо, ребята! Кажется, у меня есть намного больше, чтобы учиться :) – Darkbound

ответ

1

Забудьте наследство здесь и использовать композицию. Например, начните с основ:

общественное перечисление ItemQuality { Common, Uncommon, Rare, Эпос, Легендарный }

public class Item 
{ 
    public ItemQuality ItemQuality { get; set; } 

    // other things common to all items here 

    public List<IFeature> features { get; set; } 
} 

Так что IFeature.Ну, для начала, это пустой интерфейс:

public interface IFeature { } 

Но давайте теперь начнем добавлять оружие:

public interface IAttackWeapon : IFeature 
{ 
    int Damage { get; set; } 
} 

public interface IDefenceWeapon : IFeature 
{ 
    int Block { get; set; } 
} 

Затем мы можем начать определять некоторые классы:

public class Weapon : IAttackWeapon 
{ 
    public Damage { get; set } 
} 

public class Shield : IDefenceWeapon 
{ 
    public int Block { get; set; } 
} 

Итак, я могут определять некоторые виды оружия:

public static readonly Item ShortSword = new Item 
{ 
    ItemQuality = ItemQuality.Common, 
    Cost = 5, 
    Features = new List<IFeature> 
    { 
     new Weapon { Damage = 4 } 
    } 
} 

Принимая этот подход к композиции, если мы говорим, что вам нужен волшебный меч позднее, нам не нужно создавать больше классов, больше свойств для скрытия и т. Д. Также мы не сталкиваемся с проблемами «если мой магический меч наследует от оружие или волшебный предмет? ». Вместо этого мы добавили бы новую функцию, например:

public static readonly Item MagicSword = new Item 
{ 
    ItemQuality = ItemQuality.Rare, 
    Cost = 5000, 
    Features = new List<IFeature> 
    { 
     new Weapon { Damage = 10 }, 
     new MagicItem { Spell = Spells.TurnToFrog } 
    } 
} 
+0

Спасибо, это хорошо. Теперь я буду смотреть глубже на интерфейсы. :) – Darkbound

0

В соответствии с принципами ООП, это плохой дизайн для определения типа объекта в качестве счетчика. Хороший ООП использовал бы наследование и, возможно, полиморфизм. Как что:

public abstract class Weapon { 
    public int cost {get; set;} 
} 
public class Sword : Weapon { 
    public int damage {get; set;} 
} 
public class Shield : Weapon { 
    public int defense {get; set;} 
} 

Теперь вы можете сказать:

Sword blade = new Sword(); 
blade.cost = 5; 
blade.damage = 6; 

Shield myShield = new Shield(); 
myShield.cost = 4; 
myShield.defense = 7; 

Если вам нужен новый тип оружия, вы можете создать подкласс класса оружия, как мы сделали с мечом и щитом (скажем, вы хотите лук). Если вам нужно другое атакующее оружие, такое как нож, вы можете, например, подклассировать Меч.

public class Knife { 
    public int length {get; set;} 
} 
+0

Итак, я должен сделать новый класс для каждого типа предметов (доспехов, оружия)? Если я это сделаю, мне нужно будет создать экземпляр каждого класса, не так ли? – Darkbound

+0

Да, хороший ООП предлагает отдельный класс для каждого ТИПА. Тогда у вас может быть столько случаев, сколько вы хотите этого класса, например, массива мечей. –

+1

Но я не хочу этого. Если я это сделаю, мне нужно будет создать 15 объектов для каждого из классов, таких как Armor chest = new Armor(); затем еще один для защиты головы от другого для защиты от набегов и т. д., вместо этого я хочу, чтобы все предметы были доступны из моего экземпляра символа класса Character. Как и последние несколько строк моего основного сообщения. – Darkbound

1

Я бы не выбрал этот способ, особенно если вы хотите поддерживать хороший ООП.

Почему вы не используете интерфейсы, например, один IAttackable и IBlockable. Экран будет осуществлять IBlockable только интерфейс, меч IAttackable и IBlockable и пистолет только IAttackable

Вы бы Абэ, чтобы спросить, если объект оружия блокируемого

if (currentWeapon is IBlockable) 
    { 
     var blockWeapon = currentWeapon as IBlockable; 
     blockWeapon.blockHorizontal(); 
     blockWeapon.blockVertical(); 
    } 
Смежные вопросы