简体   繁体   English

如何向类中添加可选功能?

[英]How do I add optional functionality to a class?

I'm currently trying to learn the ins and outs of XNA/C# but I'm currently stuck on a problem: I want to add optional functionality to a class and I have no idea how to even start. 我目前正在尝试学习XNA / C#的细节,但我目前仍然遇到一个问题:我想为一个类添加可选功能,我不知道如何开始。 For clarity, here is my current code: 为清楚起见,这是我目前的代码:

public class Actor
{
    //Fields
    private Vector3 m_location;

    //Properties
    public Vector3 Location
    {
        get { return m_location; }
        set { m_location = value; }
    }

    //Constructors
    public Actor(float x, float y, float z)
    {
        Location = new Vector3(x, y, z);
    }
    public Actor(Vector3 location)
    {
        Location = location;
    }
}

public class Actor2D : Actor
{
    //Fields
    private Texture2D m_texture;

    //Properties
    public Texture2D Texture
    {
        get { return m_texture; }
        set { m_texture = value; }
    }

    //Constructors
    public Actor2D(float x, float y, float z) : base(x, y, z) {}
    public Actor2D(Vector3 vector) : base(vector) {}

    //Methods
    public void Draw(SpriteBatch spriteBatch)
    {
        spriteBatch.Draw(Texture, new Vector2(Location.X, Location.Y), Color.White);
    }
    public void Load(ContentManager content, string asset)
    {
        Texture = content.Load<Texture2D>(asset);
    }
}

The logic here is that all Actors have to have a location but they don't necessarily have to have a texture as an Actor could be a light source, trigger, etc etc. Actor2D is similar in this except that it's designated as an Actor that uses 2D texture. 这里的逻辑是所有Actors必须有一个位置,但它们不一定必须有一个纹理,因为Actor可以是光源,触发器等等.Dord2D在此类似,除了它被指定为一个Actor使用2D纹理。 What I want to do is have the ability to add functionality to either of these classes on an as needed basis. 我想要做的是能够根据需要为这些类中的任何一个添加功能。 Say I want the Actor2D to be animated or as mentioned earlier I want to add a trigger or light source to an untextured Actor... What are some ideas that would help me accomplish these goals? 假设我想要动画Actor2D或者如前所述我想为无纹理的Actor添加触发器或光源......有哪些想法可以帮助我实现这些目标?

您可以尝试查看装饰器模式 ,它允许您“粘贴”对象的行为。

If you really want object "morphing" as in objects changing their set of methods at runtime, you're looking at mixins . 如果您真的希望对象“变形”,就像在运行时更改其方法集的对象一样,那么您正在研究mixins (tutorial here ) 这里的教程)
Fair warning: it is not for the faint hearted. 公平警告:这不是为了胆小的人。

Now since at compile-time you know all the types that will have to be available, use a variety of interfaces: 现在,因为在编译时你知道所有必须可用的类型,所以使用各种接口:

  • IHasTexture IHasTexture
  • IDrawable : IHasTexture (this means and IDrawable automatically has to implement IHasTexture, since you can't draw otherwise) IDrawable:IHasTexture(这意味着IDrawable会自动实现IHasTexture,因为你无法绘制)
  • ILoadable ILoadable
  • ... as many as you want. ......尽可能多的你想要的。

Then provide an implementation for each combination you need. 然后为您需要的每个组合提供实现。 Furthermore, I think it would be best to put all this in your business layer if you have any. 此外,我认为最好将所有这些放在您的业务层中(如果有的话)。

Hope this helps, 希望这可以帮助,

Bab. 巴布。

EDIT: example. 编辑:例子。

public interface IMovable { void Move(); }

public class MoveMixin : IMovable
{
   public void Move() { Console.WriteLine("I am moving"); }
}

public class SomeDude { }

public static class TestClass
{
   public static Test()
   {
      var myMixinConfiguration = MixinConfiguration.BuildFromActive()
           .ForClass<SomeDude>().AddMixin<MoveMixin>()
           .BuildConfiguration();
      using(myMixinConfiguration.EnterScope())
      {//In this scope, SomeDude implements IMovable, but only if you get an instance through the ObjectFactory
         var myMovableDude = ObjectFactory.Create<SomeDude>(ParamList.Empty);
         ((IMovable)myMovableDude).Move(); //This line compiles and executes just fine, even though the class declaration does not specify anything about Move() !!
      }
      //The SomeDude class no longer implements IMovable
   }
}

Instead of making Actor2D (and its likes) derived from Actor . 而不是使Actor2D (和它的喜欢)派生自Actor Just change those derived classes to classes of their own, and, have one class (- Actor ) for every "Actor" with all of those properties. 只需将这些派生类更改为自己的类,并为每个具有所有这些属性的“Actor”创建一个类( - Actor )。 (An Actor2D property...) Then use whichever you need at runtime. Actor2D属性......)然后在运行时使用您需要的任何内容。

They will not take up that much resources because they will be pointing to null 's when not used. 他们不会占用那么多资源,因为他们在不使用时会指向null

EDIT: 编辑:

class Actor
{
    public Stuff2D stuff2d = new Stuff2D();
    public StuffLightPower lightPower = new StuffLightPower();
    //...
}

class Stuff2D
{
    public int height;
    public int weight;
    //...
}

class StuffLightPower
{
    public int lumen;
    public Color color;
    //...
}

And then use it like this: 然后像这样使用它:

Actor actor1 = new Actor();

//First it's going to be a 2D.
actor1.stuff2d.weight = 3;
//...

//Now it's changed to a light source.
actor1.stuff2d = null;
actor1.lightPower.color = Color.White;
//...

//And back again.
actor1.lightPower = null;
actor1.stuff2d = new Stuff2D();
//...

So, after a bunch of thinking and searching on Google/StackOverflow. 所以,经过一番思考和搜索Google / StackOverflow之后。 I've finally found my answer. 我终于找到了答案。 Rather than using a traditional OOP approach I learned that I should be using a more Component-Oriented Programming approach. 我没有使用传统的OOP方法,而是学会了使用更加面向组件的编程方法。 I found a really great link at Component based game engine design. 我在基于Component的游戏引擎设计中发现了一个非常棒的链接。

Of particular interest is the 5-part series on T=Machine describing Entity Systems which seems to be an approach which does exactly what I was looking for. 特别感兴趣的是关于T = Machine描述实体系统的5部分系列,它似乎是一种完全符合我要求的方法。 For those interested, the first post is: http://t-machine.org/index.php/2007/09/03/entity-systems-are-the-future-of-mmog-development-part-1/ . 对于那些感兴趣的人,第一篇文章是: http//t-machine.org/index.php/2007/09/03/entity-systems-are-the-future-of-mmog-development-part-1/

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM