C#成员变量继承

时间:2013-01-16 22:40:01

标签: c# variables inheritance member-variables

我对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时,其纹理最终为null。如果我在MapTile中定义纹理,我的代码工作正常,所以它与我以前的实现无关。

那么我怎样才能让GrassTile能够修改MapTile的成员变量纹理?或者让我的主类识别GrassTile的纹理,而不是MapTile,我也搞乱了接口,但我不能声明接口成员变量。我还没有得到C#继承的其他内容吗?

提前致谢

5 个答案:

答案 0 :(得分:8)

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

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;
    }
}

答案 1 :(得分:2)

你有一点语法混乱。 “new”关键字可以用作操作符来实例化某些内容,就像在main中一样,或者作为成员的修饰符来隐藏继承的成员,这就是你在GrassTile中所做的事情。你基本上是在那里重新定义你的成员。正确的版本可能是:

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

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

答案 2 :(得分:0)

继承使继承的字段在派生类中保持不变。

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

答案 3 :(得分: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

答案 4 :(得分:0)

要在代码中改进一些内容;

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

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

然后,您可以将texture的声明修改为protected,因为它不应该以这种方式在类层次结构之外真正访问。或者,将其转换为具有getset访问者的属性。

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

{
    MapTile m1 = new GrassTile(...);
    //m1.texture == null;
    GrassTile m2 = new GrassTile(...);
    //m2.texture = Main.GrassTileTexture
}