C#多态与克隆

时间:2011-01-12 05:08:11

标签: c# xna polymorphism clone

让我首先尝试解释一下我想要实现的目标。

我正在制作一款游戏,玩家可以在其中拾取能量提升(由于某种原因,我在游戏中称之为“Loot”)。所以这是我的Loot课程的一个非常基本的形式:

public class Loot : Sprite
{
    //Properties and fields...

    public Loot(/*parameters...*/)
    {
    }

    public virtual OnPickUp(Player player)
    {
    }
}

播放器精灵是来自我的课程。这是我的问题:我的精灵类持有一个位置(一个Vector2,一个来自XNA的结构代表一个向量),根据我对C#如何工作的理解,复制两个精灵将复制彼此的参考,因此,每当我改变一个人的位置时,它也会改变另一个人的位置。

每当一个战利品应该产卵时,我有一个类可以产生可以产生的可能的战利品,它会返回一个随机的战利品并将战利品复制并显示在屏幕上,但是只要我得到多个相同类型的战利品由于参考副本问题(两者将共享相同的位置并且只有一个可见),它会被弄乱。

然后,当我需要生成一个新的战利品时,我尝试创建一个新的Loot对象,所以我必须提供一个带有多个参数的构造函数,以便以这种方式轻松复制战利品: (让我们假装toSpawn可以是从Loot类派生的任何类型,比如HealthPack,或者其他什么)

Loot spawning = new Loot(toSpawn.Position, toSpawn.Color /*etc...*/);

在我决定实施“OnPickUp”之前看起来是正确的。由于我创建了一个新的 Loot 对象而不是正确的子类,因此 toSpawn OnPickUp 函数的功能将消失并拾取战利品最终什么都不做(它只会调用基类Loot的空函数)。

显然,我在这里做错了。我没有太多的编程经验,甚至没有C#,所以我真的不知道如何解决这个问题。我尝试使用Action<播放器>表示OnPickUp功能的对象,它可以工作但仍然限制了我很多(因为我必须将静态函数作为Action< Player>传递,因此限制我使用player参数的信息并阻止我使用sub - 特定信息)。

所以,最后,我的问题是:什么是更好的设计,允许子类具有重载函数,但仍然能够克隆基类及其属性?

感谢您宝贵的时间。

如果有什么不够清楚(我知道不是),那么请在评论中问我,我会尝试更详细地描述我的问题。

4 个答案:

答案 0 :(得分:4)

让你的Loot类实现ICloneable

public abstract class Loot : ICloneable
{
    public virtual object Clone()
    {
        Type type = this.GetType();
        Loot newLoot = (Loot) Activator.CreateInstance(type);
        //do copying here
        return newLoot;
    }
}

答案 1 :(得分:3)

Vector2struct而不是class,因此您的原始问题听起来像是由于对同一个Loot对象持有两个引用,而不是两个不同的Loot对象引用相同的位置。

负责创建Loot对象的类应该创建相关Loot子类的新实例,而不是创建基类。在你的设计中,Loot可能应该是一个抽象类甚至是一个接口,你应该使用abstract factory pattern来创建所需类型的Loot对象。

例如:

class LootFactory
{
    const int numLootTypes = 3;

    public Loot CreateLoot(Vector2 position)
    {
        Random rand = new Random();
        int lootIndex = rand.Next(numLootTypes);
        if (lootIndex == 0)
        {
            return new HealthPack(position);
        }
        if (lootIndex == 1)
        {
            ...
        }
        ...
    }
}

答案 2 :(得分:3)

我认为我必须错过这个问题,因为Vector2是一个结构,而不是一个类。将Vector2直接分配给另一个var v2a = new Vector2(10.0f, 20.0f); var v2b = v2a; //`v2b` is a new instance of `Vector2` distinct from `v2a`. 会自动创建副本。

PossibleLoots

您的问题听起来好像Loot类没有随机化所创建的每个PossibleLoots实例的位置。

我认为你的游戏逻辑说“每个级别最多会产生10个战利品”,所以你的Loot类会在启动时创建所有可能的public class PossibleLoots { private IList<Loot> _loots = new List<Loot>(); public PossibleLoots(int maxLoots) { for (var i = 0; i < maxLoots; i++) { _loots.Add(new Loot(this.GetRandomPosition())); } } private Vector2 GetRandomPosition() { // Your logic here to create suitable locations for loot to appear } // Rest of your `PossibleLoots` code // to spawn each `Loot` and to deplete the `_loots` // collection when the player picks up each `Loot` } 个对象,但不会除非要求“产生战利品”,否则显示一个。

所以,如果这是对的,这不是你需要的那种吗?

{{1}}

如果我错过了这个问题,请告诉我。

答案 3 :(得分:0)

对我而言,听起来你仍然是以错误的方式解决这个问题。虽然给出的答案是有效的,但这不是你应该做的事情。

如果你想要产生一个新的战利品,并且你希望它是可能的战利品类型的随机数,那么你的Loot类的构造函数应该完成所有工作。不需要克隆或ICloneable。

当创建一个新的战利品对象时,它应该随机变成它将要成为的战利品类型,不需要在某处保留所有可能类型的列表并从中克隆它们。然后新的战利品对象将拥有自己的位置和行为,并且完全像你期望的那样工作。

或者我只是误解了你想要完成的事情?