[英]How to combine objects into one list, when they are inherited from one interface?
I'm learning C# and trying to do simple object oriented exercise. 我正在学习C#,并尝试进行简单的面向对象的练习。
I have three weapon classes, "Bow,dagger,Spear", so I made one interface and inherited from this interface IWeapon. 我有三个武器类别,“弓,匕首,矛”,因此我制作了一个界面并从该界面继承了IWeapon。
Now user must choose one of the weapon, so I want to make Collection of weapons and I'm trying to make list of IWeapons, is it correct way? 现在用户必须选择一种武器,因此我想收藏武器,并尝试列出IWeapons,这是正确的方法吗? Isn't it bad practice to make list type of IWeapon ?
设置IWeapon的列表类型不是坏习惯吗? Because of, I know that Interfaces are like a contracts, and I think it's a bad idea to make List with Interface type.
因此,我知道接口就像一个合同,并且我认为用接口类型创建List是一个坏主意。 One way is to change interface to an abstract class, but I want to use Interface.
一种方法是将接口更改为抽象类,但是我想使用Interface。
private static List<IWeapon> weapons = new List<IWeapon>();
Is it correct way or not ? 这是正确的方法吗?
The only problem with your solution is that static members should be thread-safe. 解决方案的唯一问题是静态成员应该是线程安全的。 It's like a convention among C# developers.
这就像C#开发人员之间的约定。 So either change it to a non-static and, preferrably, readonly:
因此,要么将其更改为非静态(最好是只读):
private readonly List<IWeapon> weapons = new List<IWeapon>();
Or use a thread-safe collection: 或使用线程安全的集合:
private static ConcurrentBag<IWeapon> weapons = new ConcurrentBag<IWeapon>();
There's nothing wrong with using interfaces as values for lists. 使用接口作为列表的值没有错。
However, this may not be appropriate to your specific case. 但是,这可能不适用于您的特定情况。 You said you'd like the player to pick from a list of weapons.
您说过您希望玩家从武器清单中选择。 Now consider the follwing scenarios:
现在考虑以下场景:
player.Weapon = weapons[1]
, then both players will have the same instance of the weapon. player.Weapon = weapons[1]
,那么两个玩家将拥有相同的武器实例 。 If one user assings buffs to his weapons, or maybe if the weapon degrades or breaks, both the players weapons will be affected, since it is, in fact, the same weapon. The appropriate solution in this case is to save the types of weapons and present these to the player. 在这种情况下,适当的解决方案是保存武器的类型并将其提供给玩家。 Then create a new weapon instance according to the player's choice.
然后根据玩家的选择创建一个新的武器实例。
There are several different ways to do this, the simplest of which is to create an enum with the weapon types and present these to the player. 有几种不同的方法可以做到这一点,最简单的方法是用武器类型创建一个枚举并将其呈现给玩家。
So instead of the list, you can have: 因此,除了列表之外,您还可以:
public enum WeaponType
{
Bow,
Dagger,
Spear
}
And now you need to create the instance of the weapon the player chose: 现在,您需要创建玩家选择的武器的实例:
public IWeapon CreateWeapon(WeaponType weaponType)
{
switch(weaponType)
{
case WeaponType.Bow:
// Create Bow...
case WeaponType.Dagger:
// Create Dagger...
case WeaponType.Spear:
// Create Spear...
}
}
This is the basis to the Factory design pattern. 这是工厂设计模式的基础。 I would highly recommend you to take a look at it.
我强烈建议您看一下。 Here's a good place to start: http://www.dofactory.com/net/factory-method-design-pattern
这是一个不错的起点: http : //www.dofactory.com/net/factory-method-design-pattern
I have two thoughts on this: 我对此有两个想法:
I can easily imagine a situation where one would want to use a collection of a particular interface. 我可以很容易地想象出一种情况,其中有人想使用特定接口的集合。 For example, if you were writing a download queue.
例如,如果您正在编写下载队列。 You would have weapons and shields and players and villages which all implement an IDownloadableThing interface.
您将拥有全部实现IDownloadableThing接口的武器和盾牌以及玩家和村庄。 Your queue code would have a collection of IDownloadableThings because it doesn't care what its actually downloading, it just cares that that thing know what its URL or file path or whatever is.
您的队列代码将具有IDownloadableThings集合,因为它不在乎其实际下载的内容,它只是在乎那个东西知道它的URL或文件路径是什么。
I'm a little wary of developer edicts. 我对开发者命令有些警惕。 There are good ideas and traps you should be aware of in any language, but context can change everything.
您应该以任何一种语言了解一些好主意和陷阱,但是上下文可以改变一切。 When you are trying to figure out if 'Weapon' should be an abstract class, ask yourself a couple things.
当您试图弄清楚“武器”是否应该是抽象类时,请问自己几件事。 Should a class implementing Weapon also be allowed to be a Shield?
实施武器的职业是否也应该成为盾牌? If locking down multiple inheritance is important, then abstract classes are the way to do that.
如果锁定多重继承很重要,那么抽象类就是做到这一点的方法。 Will there be a lot or any common behavior that classes implementing 'Weapon' will want to share?
实现“武器”的类会分享很多或任何常见的行为吗? For example, is there a CalculateDamage() method that's basically identical between all 'Weapon' implementations.
例如,是否有一个CalculateDamage()方法在所有“武器”实现之间基本相同。 Once you have answers to what a class of interface's purpose is, then it'll be easier to choose to violate a development guideline because the situation requires it or re-think your approach.
一旦您对一类接口的用途有了答案,那么就容易选择违反开发指南,因为情况需要这样做或重新考虑您的方法。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.