【问题标题】:Static object defined in base should be different for child classes基类中定义的静态对象对于子类应该不同
【发布时间】:2014-02-20 16:36:40
【问题描述】:

我有一个基类BaseClass,它有一个纹理或位图。两个类派生自它,比如说AChildBChild。每个子类设置纹理。现在每个子类的纹理将保持不变。我不希望每个子类的对象有多个纹理变量。我希望它是单例的。

这是一些代码。

abstract class BaseClass
{
    public Texture TextureImage { get; set; }
    public Texture LoadTexture(string path)
    {
         return some texture using path,
    }
}

class AChild : BaseClass
{
    AChild()
    {
         if (TextureImage == null)
             TextureImage = LoadTexture(PathToImageA);
    }
}

class BChild : BaseClass
{
    BChild()
    {
         if (TextureImage == null)
             TextureImage = LoadTexture(PathToImageB);
    }
}

Main()
{
     var aOne = new AChild();
     var aTwo = new AChild();

     var bOne = new BChild();
     var bTwo = new BChild();

}

现在您可以看到,每当我创建AChildBChild 的对象时,都会创建一个新纹理。我想要实现的是,每当创建 AChild 的第一个孩子(aOne)时,应该初始化 TextureImage,并且当创建另一个对象(aTwo)时,它使用第一个孩子创建的纹理。

我尝试在基类中将 TextureImage 设为静态,但之后 bOne 纹理是 aOne 创建的。

我确信这可能是我想要的,但问题是如何实现?

【问题讨论】:

  • 听起来您需要在子类中进行覆盖或将基类设为接口并在子类中实现静态。
  • @crashmstr 你能帮我写代码吗,我正在尝试这样做但失败了。
  • 只需删除 AChild 类中 == null 的测试并使 TextureObject 成为静态即可。 BChild 仍然测试 null。
  • @Steve 他希望所有AChild 都有一个TextureImagePathToImageA,所有BChild 都有一个不同PathToImageB 的。跨度>

标签: c# inheritance static


【解决方案1】:

受到 crashmstr 评论和良好睡眠的启发,我想出了这个解决方案

class Program
{
    static void Main(string[] args)
    {
        AChild a1 = new AChild();
        Console.WriteLine(a1.TextureImage.Path);
        BChild b = new BChild();
        Console.WriteLine(b.TextureImage.Path);
        AChild a2 = new AChild();
        Console.WriteLine(a2.TextureImage.Path);
    }
}

public class Texture
{
    public string Path { get; set; }

}

public abstract class BaseClass
{
    public static ConcurrentDictionary<Type, Texture> TextureImageCache { get; set; }

    static BaseClass()
    {
        TextureImageCache = new ConcurrentDictionary<Type, Texture>();
    }

    public virtual Texture TextureImage
    {
        get
        {
            return TextureImageCache.GetOrAdd(
                this.GetType(),
                t => this.LoadTexture(this.TexturePath));
        }
    }

    public Texture LoadTexture(string path)
    {
        return new Texture { Path = path };
    }

    public abstract string TexturePath { get; }
}

public class AChild : BaseClass
{

    public override string TexturePath
    {
        get { return "iamgeA"; }
    }
}

public class BChild : BaseClass
{

    public override string TexturePath
    {
        get { return "imageB"; }
    }
}

一些亮点:

  • 仅在第一次需要时加载纹理的 ConcurrentDictionary(延迟加载)
  • 基类只使派生类实现Path 属性。
  • 我坚信这是一个优雅而强大的解决方案,无需在派生类中直接操作 type,而且它可以很容易地扩展到新的派生类

【讨论】:

  • 使用这种方法,我可能会“隐藏”Dictionary 并且仍然让TextureImage 返回Texture
  • @Faisal:这行得通吗?如果是,请点赞并接受答案;否则告诉我可以改变什么
【解决方案2】:

这未经测试,但我认为这会做你想要的。 在每个子类中,有一个私有的Textureoverride 基类的TextureImage 以使用子类自己的静态版本。

abstract class BaseClass
{
    public static Texture TextureImage { get; set; }
    public Texture LoadTexture(string path)
    {
         //return some texture using path,
    }
}

class AChild : BaseClass
{
    private static Texture TextureImageA { get; set; }
    public override Texture TextureImage 
    {
        get { return TextureImageA; }
        set { TextureImageA = value; }
    }

    AChild()
    {
         if (TextureImage == null)
             TextureImage = LoadTexture(PathToImageA);
    }
}

class BChild : BaseClass
{
    private static Texture TextureImageB { get; set; }
    public override Texture TextureImage 
    {
        get { return TextureImageB; }
        set { TextureImageB = value; }
    }

    BChild()
    {
         if (TextureImage == null)
             TextureImage = LoadTexture(PathToImageB);
    }
}

【讨论】:

    【解决方案3】:

    我修改了答案以在 AChild 和 BChild 中使用抽象属性和覆盖。

    BaseClass abstract 中创建TextureImage 属性。然后,覆盖AChild & BChild 中的抽象属性:

    abstract class BaseClass
    {
        public abstract Texture TextureImage { get; }
        private Texture _TextureImage;
    }
    
    class AChild : BaseClass
    {
        public override Texture TextureImage {
            get {
              if ( _TextureImage == null )
                  _TextureImage = LoadTexture(PathToImageA);
              return _TextureImage;
            }
        }
    }
    
    class BChild : BaseClass
    {
        public override Texture TextureImage {
            get {
              if ( _TextureImage == null )
                  _TextureImage = LoadTexture(PathToImageB);
              return _TextureImage;
            }
        }
    }
    
    Main()
    {
         var aOne = new AChild();
         var aTwo = new AChild();
    
         var bOne = new BChild();
         var bTwo = new BChild();
    
    }
    

    【讨论】:

    • 它没有用。创建第一个孩子时,BChild.TextureImage 不为空,
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-04-04
    • 2023-03-25
    • 2023-03-20
    • 1970-01-01
    • 2018-01-30
    • 1970-01-01
    • 2021-11-20
    相关资源
    最近更新 更多