简体   繁体   English

从一个接口继承对象时,如何将它们组合到一个列表中?

[英]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: 现在考虑以下场景:

  1. You have a single player in your game, and he chose a single weapon. 您的游戏中只有一个玩家,而他选择了一个武器。 You have created a whole list worth of weapon instances that no one will ever need or use. 您已经创建了一个完整的清单,列出了没人需要或不会使用的武器实例。 This just wastes memory. 这只会浪费内存。
  2. You have multiple players in the game, and they both choose the same weapon. 您在游戏中有多个玩家,他们都选择相同的武器。 This could be even worse. 这可能更糟。 If you assign the weapons like this: 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. 如果一个用户对他的武器进行抛光,或者如果该武器退化或断裂,那么两个玩家的武器都会受到影响,因为实际上这是同一把武器。 Think of it like this, both you and I would like a chocolate cake. 这样想吧,我和你都想要一块巧克力蛋糕。 The store can either give us both the same piece of cake, in this case, if you eat it, I will have none. 商店可以给我们两个蛋糕,在这种情况下,如果您吃了,我将一无所有。 Or they can bake us both new cakes, so each of us can have his own. 或者他们可以给我们两个新蛋糕烤,所以我们每个人都可以拥有自己的蛋糕。

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: 我对此有两个想法:

  1. 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或文件路径是什么。

  2. 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.

相关问题 如何通过组合每个列表中的一个元素将两个不同对象的列表组合成一个列表? - How to combine two list of different objects into one list by combining one element from each list? 如何合并从一个类继承的多个子类的所有功能 - how to combine all functions of multi subclasses inherited from one class 如何访问列表<Interface>从接口继承类时的对象属性? - How to access List<Interface> object properties when it's class is inherited from interface? 如何更好地组合从一种干扰中继承的不同类型的通用列表? - How better combine generic lists of different types inherited from one interfase? 如何将两个对象的字段组合成一个对象? - How can I combine fields from two objects into one? 如何使nhibernate不合并继承对象的结果? - How to make nhibernate not combine results from inherited objects? 在将多态化为接口对象之后,如何保留从一个类继承的属性? - How do you keep inherited properties from one class after polymorphing to an interface object? 将一对多列表组合成一个平面对象列表 C# - Combine one to many lists into one flat list of objects C# 将两个对象合并为一个 - Combine two objects into one 2个COM对象,并从另一个对象使用接口 - 2 COM objects and using interface from one of it in another
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM