我对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#继承的其他内容吗?
提前致谢
答案 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,因为它不应该以这种方式在类层次结构之外真正访问。或者,将其转换为具有get
和set
访问者的属性。
最后,您对new修饰符的使用不正确。此修饰符仅用于(在此上下文中)允许您使用新行为覆盖某些行为的基本实现(而不是继承基本行为)。在这种情况下,您在GrassTile中声明一个“新”纹理,(不必要)将覆盖基本实例,但仅限于通过GrassTile类引用时。
{
MapTile m1 = new GrassTile(...);
//m1.texture == null;
GrassTile m2 = new GrassTile(...);
//m2.texture = Main.GrassTileTexture
}