簡體   English   中英

C#多態性與克隆

[英]C# polymorphism with cloning

首先讓我解釋一下我要實現的目標。

我正在制作一款游戲,玩家可以在游戲中拾取道具(由於某種原因,我稱其為“戰利品”)。 所以這是我的Loot類的一個非常基本的形式:

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

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

    public virtual OnPickUp(Player player)
    {
    }
}

PlayerSprite是我的課程。 這是我的問題:我的Sprite類擁有一個位置(Vector2,它是XNA中表示矢量的結構),並且根據我對C#的工作原理的理解,復制兩個Sprite會復制彼此的引用 ,因此,每當我更改位置時,也會改變另一個。

每當生成戰利品時,我都會擁有一類持有可能生成的戰利品的類,它會隨機返回一個戰利品,並將戰利品復制並顯示在屏幕上,但是一旦我獲得多個同類型的戰利品,它就會由於參考副本問題而混亂(兩者將共享同一位置,並且只有一個位置可見)。

因此,當我需要生成新的戰利品時,我嘗試創建一個新的Loot對象,因此我必須為構造函數提供多個參數,以這種方式輕松復制戰利品:(讓我們假裝為spawn可以是從Loot類派生的任何類型,例如HealthPack或其他任何東西)

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

在我決定實施“ OnPickUp”之前,它看起來一直不錯。 由於我創建了一個新的Loot對象而不是適當的子類,因此toSpawnOnPickUp函數的功能將消失,拾取贓物最終將無濟於事(它只會調用基類Loot的empty函數)。

顯然,我在這里做錯了。 我沒有太多的編程經驗,甚至沒有C#的經驗,所以我真的不知道如何解決這個問題。 我嘗試使用代表OnPickUp功能的Action <Player>對象,它可以工作,但仍然對我有很多限制(因為我必須將靜態函數作為Action <Player>傳遞,因此限制了我使用播放器的信息參數,並阻止我使用子類的特定信息)。

因此,最后,我的問題確實是: 允許子類具有重載函數,但仍然能夠克隆基類及其屬性的方法什么更好的設計?

謝謝您的寶貴時間。

如果尚不清楚(我知道還不清楚),請在評論中問我,我將嘗試更詳細地描述我的問題。

讓您的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;
    }
}

Vector2是一個struct而不是一個class ,因此您的原始問題聽起來像是由於持有對同一個Loot對象的兩個引用,而不是擁有對同一個位置的引用的兩個不同的Loot對象。

負責創建Loot對象的類應該創建相關Loot子類的新實例,而不是創建基類。 在您的設計中,Loot可能應該是一個抽象類甚至是一個接口,並且您應該使用抽象工廠模式來創建所需類型的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)
        {
            ...
        }
        ...
    }
}

我認為我一定會對此問題有所遺漏,因為Vector2是結構而不是類。 將一個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實例的位置。

我假設您的游戲邏輯說的是“每個級別最多可以產生10個掠奪物”,因此您的PossibleLoots類在啟動時會創建所有可能的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`
}

如果我錯過了這個問題的重點,請告訴我。

對我來說,聽起來真的像是您在以錯誤的方式前進。 盡管給出的答案會奏效,但這不是您必須要做的。

如果您想生成一個新的戰利品,並且希望它是可能的各種類型的戰利品,那么您的Loot類的構造函數應該可以完成所有工作。 不需要克隆或ICloneable。

當創建一個新的戰利品對象時,它應該隨機成為它的戰利品類型,而無需在所有地方保留所有可能類型的列表並從中進行克隆。 這樣,新的戰利品對象將具有自己的位置和行為,並且可以完全按您期望的方式工作。

還是我只是誤解了您要完成的工作?

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM