Question

I'm a little new to C#, but I have a fairly extensive background in programming.

What I'm trying to do: Define different MapTiles for a game. I've defined the base MapTile class like this:

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

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

I then define a subclass GrassTile like this:

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:

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.

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?

Thanks in advance

Was it helpful?

Solution

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

OTHER TIPS

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:

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

as your rectangle gets set in the base constructor anyway.

Inheritance make inherited fields persist in derived class.

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

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 "Operator"

The new operator is used to create objects and invoke constructors, for example:

Class1 MyClass  = new Class1();

new Modifier

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.

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:

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.

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.

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).

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).

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.

Finally, your use of the new modifier 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.

{
    MapTile m1 = new GrassTile(...);
    //m1.texture == null;
    GrassTile m2 = new GrassTile(...);
    //m2.texture = Main.GrassTileTexture
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top