C#成员变量继承
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/14369232/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
C# Member variable inheritance
提问by Logicon211
I'm a little new to C#, but I have a fairly extensive background in programming.
我对 C# 有点陌生,但我有相当广泛的编程背景。
What I'm trying to do: Define different MapTiles for a game. I've defined the base MapTile class like this:
我想要做的是:为游戏定义不同的 MapTiles。我已经像这样定义了基本的 MapTile 类:
public class MapTile
{
public Texture2D texture;
public Rectangle mapRectangle;
public MapTile(Rectangle rectangle)
{
this.mapRectangle = rectangle;
}
}
I then define a subclass GrassTile like this:
然后我像这样定义一个子类 GrassTile:
class GrassTile : MapTile
{
new Texture2D texture = Main.GrassTileTexture;
new public Rectangle mapRectangle;
public GrassTile(Rectangle rectangle) : base(rectangle)
{
this.mapRectangle = rectangle;
}
}
In my Main class I'm creating a new maptile like this:
在我的 Main 类中,我正在创建一个新的 maptile,如下所示:
Maptile testTile;
testTile = new GrassTile(new Rectangle(0, 0, 50, 50);
However, when I try to render this testTile, its texture ends up being null. My code works fine if I define the texture inside MapTile, so it has nothing to do with my previous implementation of it.
但是,当我尝试渲染这个 testTile 时,它的纹理最终为空。如果我在 MapTile 中定义纹理,我的代码工作正常,所以它与我之前的实现无关。
So how can I get GrassTile to be able to modify MapTile's member variable texture? or get my main class to recognize GrassTile's texture instead of MapTile's I fiddled with interfaces as well, but I can't declare interface member variables. Is there something else to C# inheritance that I don't get yet?
那么如何让 GrassTile 能够修改 MapTile 的成员变量纹理呢?或者让我的主类识别 GrassTile 的纹理而不是 MapTile 的纹理 我也摆弄过接口,但我不能声明接口成员变量。我还没有了解 C# 继承的其他内容吗?
Thanks in advance
提前致谢
采纳答案by Sergey Berezovskiy
Child class will inherit members of parent class. You don't need to specify them. Also it's better to use properties rather than public fields.
子类将继承父类的成员。您不需要指定它们。此外,最好使用属性而不是公共字段。
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;
}
}
回答by canahari
You have a little bit of a syntax confusion. "new" keyword can either be used as an operator to instantiate something, as you do in your main, or as a modifier to members to hide inherited members and that's what you're doing in your GrassTile. You're essentially redefining your members there. Correct version might be:
你有一点语法混乱。“new”关键字既可以用作操作符来实例化某些东西,就像您在 main 中所做的那样,也可以用作成员的修饰符以隐藏继承的成员,这就是您在 GrassTile 中所做的。你基本上是在那里重新定义你的成员。正确的版本可能是:
class GrassTile : MapTile
{
public GrassTile(Rectangle rectangle) : base(rectangle)
{
texture = Main.GrassTileTexture;
}
}
as your rectangle gets set in the base constructor anyway.
因为您的矩形无论如何都在基本构造函数中设置。
回答by Tommaso Belluzzo
Inheritance make inherited fields persist in derived class.
继承使继承的字段在派生类中持久化。
public sealed class GrassTile : MapTile
{
public GrassTile(Rectangle rectangle) : base(rectangle)
{
texture = Main.GrassTileTexture;
}
}
回答by Mr. Young
I think it's best here to clarify how you are using the new
keyword. new
can be used in two fashions. As an operator and as a modifier.
我认为最好在这里澄清您如何使用new
关键字。new
可以以两种方式使用。作为运算符和修饰符。
new
"Operator"
new
“操作员”
The new operator is used to create objects and invoke constructors, for example:
new 运算符用于创建对象和调用构造函数,例如:
Class1 MyClass = new Class1();
new
Modifier
new
修饰符
Use the new modifier to explicitly hide a member inherited from a base class. To hide an inherited member, declare it in the derived class using the same name, and modify it with the new modifier.
使用 new 修饰符显式隐藏从基类继承的成员。要隐藏继承的成员,请在派生类中使用相同的名称声明它,并使用 new 修饰符修改它。
Consider the following class:
考虑以下类:
public class MyBaseC
{
public int x;
public void Invoke() {}
}
Declaring a member with the name Invoke in a derived class will hide the method Invoke in the base class, that is:
在派生类中声明名为 Invoke 的成员将隐藏基类中的 Invoke 方法,即:
public class MyDerivedC : MyBaseC
{
new public void Invoke() {}
}
However, the field x will not be affected because it is not hidden by a similar name.
但是,字段 x 不会受到影响,因为它没有被相似的名称隐藏。
Name hiding through inheritance takes one of the following forms:
通过继承隐藏名称采用以下形式之一:
A constant, field, property, or type introduced in a class or struct hides all base class members with the same name.
A method introduced in a class or struct hides properties, fields, and types, with the same name, in the base class. It also hides all base class methods with the same signature.
An indexer introduced in a class or struct hides all base class indexers with the same signature.
在类或结构中引入的常量、字段、属性或类型隐藏了所有同名的基类成员。
在类或结构中引入的方法在基类中隐藏了具有相同名称的属性、字段和类型。它还隐藏具有相同签名的所有基类方法。
在类或结构中引入的索引器隐藏具有相同签名的所有基类索引器。
Since you are name hiding and declaring a Maptile
type but initializing to a child GrassTile
type AND parent MapTile
type never initialized your Texture
member is the reason why you seeing a null
.
由于您正在名称隐藏和声明Maptile
类型但初始化为子GrassTile
类型并且父MapTile
类型从未初始化您的Texture
成员是您看到null
.
回答by RJ Lohan
A few things to improve on in your code;
代码中需要改进的一些地方;
Firstly, the property Texture
is already defined in the base class MapTile, so it does not need to be re-defined in the class GrassTile
; the derived class (GrassTile) inherits this member from the base class (MapTile).
首先,该属性Texture
已经在基类 MapTile 中定义,所以不需要在类中重新定义GrassTile
;派生类 (GrassTile) 从基类 (MapTile) 继承该成员。
Next, you might consider modifying the base class 'MapTile' to be abstract, as I presume it has no direct behaviour itself (the texture must be provided by concrete dervied class implemenations).
接下来,您可能会考虑将基类 'MapTile' 修改为abstract,因为我认为它本身没有直接行为(纹理必须由具体的派生类实现提供)。
Then, you can modify the declaration of texture
to be protected, as it should not really be accessed outside the class hierarchy this way. Or else, turn it into a property with get
and set
accessors.
然后,您可以修改texture
to be protected的声明,因为它不应该以这种方式在类层次结构之外真正被访问。否则,将其转换为带有get
和set
访问器的属性。
Finally, your use of the newmodifier is incorrect. This modifier is only intended (in this context) to allow you to override a base implementation of some behaviour with a new behaviour (rather than inheriting base behaviour). In this case, you are declaring a 'new' texture in GrassTile, which (is unnecessary) will override the base instance, but ONLY when referenced via the class GrassTile.
最后,您对new修饰符的使用是不正确的。此修饰符仅用于(在此上下文中)允许您使用新行为(而不是继承基本行为)覆盖某些行为的基本实现。在这种情况下,您在 GrassTile 中声明了一个“新”纹理,这(是不必要的)将覆盖基本实例,但仅当通过类 GrassTile 引用时。
{
MapTile m1 = new GrassTile(...);
//m1.texture == null;
GrassTile m2 = new GrassTile(...);
//m2.texture = Main.GrassTileTexture
}