带有构造器的通用类<t>选择类型

时间:2018-07-06 13:16:54

标签: c# class generics

我有三个具有相同命名属性的类。假设类为SwordBowHammer,而属性为DamageRange。如何通过构造函数实例化Weapon<T>的类,并在其中传递int以选择此类的Type?

我不确定这是否是我想要做的正确方法。

public class Weapon<T>
{
}

public  class Sword
{
    public int Damage { get => 10; }
    public int Range { get => 12; }
}

public class Bow
{
    public int Damage { get => 8; }
    public int Range { get => 28; }
}

public class Hammer
{
    public int Damage { get => 15; }
    public int Range { get => 8; }
}

5 个答案:

答案 0 :(得分:6)

您所描述的称为工厂模式。您有一些工厂可以实例化其他对象,在这种情况下,取决于整数:

class WeaponFactory
{
    public static IWeapon CreateWeapon(WeaponType type)
    {
        switch type:
            case WeaponType.Sword: return new Sword();
            case WeaponType.Hammer: return new Hammer();
            case WeaponType.Bow: return new Bow();
            default: throw new ArgumentException("Unknown weaponType");
    }
}
enum WeaponType { Sword, Hammer, Bow }
interface IWeapon
{
    int Damage { get; }
    int Range { get; }
}

最后,所有类都应实现该接口。现在,您可以使用以下代码轻松创建实例:

var hammer = WeaponFactory.CreateWeapon(WeaponType.Hammer);

答案 1 :(得分:5)

除了您提出的其他解决方案之外,我还将简化此操作。

public class Weapon
{
    private int _range;
    private int _damage;

    public Weapon(int range, int damage)
    {
        _range = range;
        _damage = damage;
    }

    public int Range => _range;
    public int Damage => _damage;
}

这里实际上不需要多态-您要做的就是在运行时分配不同的只读值。如果以后想要每种武器的行为不同,则可以使用策略模式来实现。

然后我只需要使用工厂来实例化不同的武器。

这些工厂的外观取决于调用方式,但实际上,您的工厂方法可能如下所示:

public Weapon GetWeapon(string weaponType)
{
    var weaponProperties = propertiesFor(weaponType);
    return new Weapon(weaponProperties.Range, weaponProperties.Damage);
}

propertiesFor在字典,文件等中查找给定武器类型的适当值。

除非您确实需要在运行时提供武器的不同实现,否则我将避免使用IWeapon接口。直到您需要它之前,都不要写它。声明接口只是为了在测试中进行模拟(正如其他人所建议的那样)通常会向我表明您的测试边界已关闭,或者您有一些依赖关系可以更好地隔离(但这是更广泛的讨论)。

答案 2 :(得分:4)

public interface IWeapon
{
    int Damage { get; }
    int Range { get; }
}

public class Weapon : IWeapon
{
    protected int _damage, _range;

    public int Damage
    {
        get { return _damage; }
    }

    public int Range
    {
        get { return _range; }
    }
}

public class Sword : Weapon
{
    public Sword()
    {
        _damage = 10;
        _range = 12;
    }
}

public class Bow : Weapon
{
    public Bow()
    {
        _damage = 8;
        _range = 28;
    }
}

public class Hammer : Weapon
{
    public Hammer()
    {
        _damage = 15;
        _range = 8;
    }
}

答案 3 :(得分:2)

从基类继承

public class Weapon
{
    public int Damage { get; set; }
    public int Range { get; set; }
}

public class Sword : Weapon
{
}

public class Bow : Weapon
{
}

public class Hammer : Weapon
{
}

并通过这种方式实例化

Weapon item = new Sword() { Damage = 10, Range = 20 };

答案 4 :(得分:1)

您可以从为父武器类创建界面开始。然后用子类扩展武器类,以制作剑,锤子等。然后,您可以为每个子类添加自定义属性,并且仍将它们用作武器,因为它们共享相同的接口/父类并且都具有攻击方法。

public interface IWeapon
{
    int Damage { get; }
    int Range { get; }
    void Attack();
}

public class Weapon : IWeapon
{
    public int Damage { get; private set; }
    public int Range { get; private set; }

    public Weapon(int damage, int range)
    {
        Damage = damage;
        Range = range;
    }

    public virtual void Attack()
    {
        Console.WriteLine("Weapon: Attack");
    }
}

public class Sword : Weapon
{
    //some sword properties here...

    public Sword(int damage, int range) : base(damage, range)
    {

    }

    public override void Attack()
    {
        Console.WriteLine("Weapon Sword: Attack");
    }
}

public class Bow : Weapon
{
    //some bow properties here...

    public Bow(int damage, int range) : base(damage, range)
    {

    }

    public override void Attack()
    {
        Console.WriteLine("Weapon Bow: Attack");
    }
}

public class Hammer : Weapon
{
    //some hammer properties here...

    public Hammer(int damage, int range) : base(damage, range)
    {

    }

    public override void Attack()
    {
        Console.WriteLine("Weapon Hammer: Attack");
    }
}

class Program
{
    public static void Main(string[] args)
    {
        IWeapon hammerWeapon = new Hammer(15, 10);
        hammerWeapon.Attack();
    }
}