2013-01-16 178 views
4

我对C#有点新,但是在编程方面我有相当广泛的背景。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; 
    } 
} 

在我的主类我创建这样一个新的maptile:

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

但是,当我尝试渲染此testTile时,其纹理结束为空。如果我在MapTile中定义纹理,我的代码工作正常,所以它与我以前的实现无关。

那么我该如何让GrassTile能够修改MapTile的成员变量纹理?或者让我的主类识别GrassTile的纹理,而不是MapTile的我也使用接口,但我无法声明接口成员变量。有没有其他的C#继承,我还没有得到?

在此先感谢

+0

您能否澄清对Main.GrassTileTexture的引用?这是一个静态属性? – jake

+0

对不起,它的静态属性在分配给MapTile时正常工作,而不是GrassTile。 – Logicon211

回答

7

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

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

谢谢,这对我有用。快速的问题,财产是不是我可以在C#中定义的东西,我试过“财产”和“公共财产”,没有显示任何东西。 另外,那些{get;组; }块没有必要,它们是干什么用的? – Logicon211

+0

@ Logicon211属性在C#中有特定的语法,您可以在[msdn about properties](http://msdn.microsoft.com/zh-cn/library/x9fsa0sw.aspx)上阅读。另外'{get;组; }'block是[自动实现的属性定义](http://msdn.microsoft.com/en-us/library/bb384054.aspx)的一部分。我认为这将是非常有用的你阅读[公共领域和属性之间的区别](http://stackoverflow.com/questions/653536/difference-between-property-and-field-in-c-sharp-净-3-5)。对不起没有反应 - 是AFK。 –

2

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

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

因为你的矩形在基础构造函数中被设置。

+0

阅读更多在http://msdn.microsoft.com/en-us/library/6fawty39(v=vs.80).aspx – canahari

+0

另一件事是,你不应该使用这样的静态变量。 C#被认为是纯粹的面向对象,而我的面向对象的感觉说,即使你绝对必须使用一个静态变量,你应该在它逻辑上属于的类中去做。在这种情况下,我会说它应该是MapTile.GrassTexture或GrassTile.Texture – canahari

0

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

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

我认为这是最好的在这里澄清你如何使用new关键字。 new可用于两种时尚。作为运营商和修改者。

new

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

Class1 MyClass = new Class1(); 

new修改

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

考虑下面的类:

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

在派生类声明的名称调用成员将隐藏方法Invoke在基类,即:

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

然而,字段x不会受到影响,因为它没有被类似名称隐藏。

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

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

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

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

既然你的名字隐藏和声明Maptile类型,但初始化为孩子GrassTile类型和父MapTile型从未初始化,您Texture成员就是为什么你看到null的原因。

0

在代码中需要改进的几件事;

首先,属性Texture已经在基类MapTile中定义了,所以不需要在类GrassTile中重新定义;派生类(GrassTile)从基类(MapTile)继承此成员。接下来,您可能会考虑将基类'MapTile'修改为abstract,因为我认为它本身没有直接行为(纹理必须由具体的dervied类实现提供)。

然后,您可以将texture的声明修改为protected,因为它不应该以这种方式真正在类层次结构外访问。否则,将其转变为getset访问者的财产。

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

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