6

我对 C# 有点陌生,但我在编程方面有相当广泛的背景。

我正在尝试做的事情:为游戏定义不同的 MapTiles。我已经像这样定义了基本的 MapTile 类:

public class MapTile
{
    public Texture2D texture;
    public Rectangle mapRectangle;

    public MapTile(Rectangle rectangle)
    {
        this.mapRectangle = rectangle;
    }
}

然后我像这样定义一个子类 GrassTile:

class GrassTile : MapTile
{
    new Texture2D texture = Main.GrassTileTexture;
    new public Rectangle mapRectangle;

    public GrassTile(Rectangle rectangle) : base(rectangle)
    {
        this.mapRectangle = rectangle;
    }
}

在我的 Main 类中,我正在创建一个新的 maptile,如下所示:

Maptile testTile;
testTile = new GrassTile(new Rectangle(0, 0, 50, 50);

但是,当我尝试渲染这个 testTile 时,它​​的纹理最终为空。如果我在 MapTile 中定义纹理,我的代码可以正常工作,因此它与我之前的实现无关。

那么如何让 GrassTile 能够修改 MapTile 的成员变量纹理呢?或者让我的主类识别 GrassTile 的纹理而不是 MapTile 的我也摆弄了接口,但我不能声明接口成员变量。C# 继承还有什么我还没有得到的吗?

提前致谢

4

5 回答 5

8

子类将继承父类的成员。您无需指定它们。此外,最好使用属性而不是公共字段。

public class MapTile
{
    public Texture2D Texture { get; set; }
    public Rectangle MapRectangle { get; set; }

    public MapTile(Rectangle rectangle)
    {
        MapRectangle = rectangle;
    }
}

public class GrassTile : MapTile
{    
    public GrassTile(Rectangle rectangle) : base(rectangle)
    {
        Texture = Main.GrassTileTexture;
    }
}
于 2013-01-16T22:43:12.213 回答
2

你有一点语法混乱。“new”关键字既可以用作运算符来实例化某些东西,就像您在 main 中所做的那样,也可以用作成员的修饰符以隐藏继承的成员,这就是您在 GrassTile 中所做的。您实质上是在那里重新定义您的成员。正确的版本可能是:

   class GrassTile : MapTile
    {
        public GrassTile(Rectangle rectangle) : base(rectangle)
        {
            texture = Main.GrassTileTexture;
        }
    }

因为您的矩形无论如何都在基本构造函数中设置。

于 2013-01-16T22:47:31.163 回答
0

继承使继承的字段保留在派生类中。

public sealed class GrassTile : MapTile
{
    public GrassTile(Rectangle rectangle) : base(rectangle)
    {
        texture = Main.GrassTileTexture;
    }
}
于 2013-01-16T22:52:09.480 回答
0

我认为最好在这里澄清您如何使用new关键字。new可以以两种方式使用。作为运算符和修饰符。

new“操作员”

new 运算符用于创建对象和调用构造函数,例如:

Class1 MyClass  = new Class1();

new修饰符

使用 new 修饰符显式隐藏从基类继承的成员。要隐藏继承的成员,请在派生类中使用相同的名称声明它,并使用 new 修饰符对其进行修改。

考虑以下类:

public class MyBaseC 
{
   public int x;
   public void Invoke() {}
}

在派生类中声明一个名为 Invoke 的成员会隐藏基类中的方法 Invoke,即:

public class MyDerivedC : MyBaseC
{
   new public void Invoke() {}
}

但是,字段 x 不会受到影响,因为它没有被相似的名称隐藏。

通过继承隐藏名称采用以下形式之一:

  • 在类或结构中引入的常量、字段、属性或类型会隐藏所有具有相同名称的基类成员。

  • 在类或结构中引入的方法将同名的属性、字段和类型隐藏在基类中。它还隐藏了所有具有相同签名的基类方法。

  • 在类或结构中引入的索引器隐藏了所有具有相同签名的基类索引器。

由于您是隐藏名称并声明Maptile类型但初始化为子GrassTile类型和父MapTile类型从未初始化您的Texture成员是您看到null.

于 2013-01-16T22:58:32.350 回答
0

代码中有一些需要改进的地方;

首先,该属性Texture已在基类 MapTile 中定义,因此无需在类中重新定义GrassTile;派生类 (GrassTile) 从基类 (MapTile) 继承此成员。

接下来,您可能会考虑将基类 'MapTile' 修改为abstract,因为我认为它本身没有直接行为(纹理必须由具体的派生类实现提供)。

然后,您可以修改textureto be protected的声明,因为它不应该真正以这种方式在类层次结构之外访问。否则,将其变成带有getset访问器的属性。

最后,您对new修饰符的使用不正确。此修饰符仅用于(在此上下文中)允许您使用新行为(而不是继承基本行为)覆盖某些行为的基本实现。在这种情况下,您在 GrassTile 中声明了一个“新”纹理,这(不必要)将覆盖基本实例,但仅在通过类 GrassTile 引用时。

{
    MapTile m1 = new GrassTile(...);
    //m1.texture == null;
    GrassTile m2 = new GrassTile(...);
    //m2.texture = Main.GrassTileTexture
}
于 2013-01-16T23:06:57.847 回答