Mastro
Mastro

Reputation: 1497

Overriding Inherited Class' Constructor but still calling base afterwards

I've looked at so many possible answers in my searching and even all the ones suggested as I type this with no luck. I figure I might not even be wanting inheritance. Currently everything works, here's a sample of what I have.

This currently works as expected:

public class PlayerShip : Sprite
{
    public PlayerShip(Texture2D texture, Vector2 position, Rectangle boundry)
        : base(texture, position, boundry, 2, 2, 14)
    {
        //Set some "PlayerShip" specific properties
    }
}

public class Sprite //The Base Class
{
    public Sprite(Texture2D texture, Vector2 position, Rectangle boundry) : this(texture, position, boundry, 1, 1, 1)
    {}

    public Sprite(Texture2D texture, Vector2 position, Rectangle boundry, int rows, int cols, double framesPerSecond)
    {
        //Set a bunch of properties here
    }
    //other methods with virtual keyboard that I can override if I choose
}

The problem comes in when I want to change the PlayerShip class to be loaded without the "texture" parameter in place of something else. I want to load up the "texture" parameter in the PlayerShip constructor, remove the Position parameter and then pass it off to the base. I can't use virtual or abstract on the base constructor to override and I get an error that I must have "texture"

So this fails:

    public PlayerShip(ContentManager content, Rectangle boundry)
    {
        base(content.Load<Texture2D>("Image"), boundry);
        //Set some "PlayerShip" specific properties
    }

Error: Method, delegate or event expected on line base. But I can't do it the : base way because texture isn't part of the parameters.

So then I thought I'd put it on the base but I don't want it on the base because I only want some classes that inherit to use this new parameter. Since I don't know what the value will be I have to load it up empty. But I can't call the original constructor like this

     public Sprite(ContentManager content, Rectangle boundry) 
: this(content.Load<Texture2D>(""), position, boundry) //<-- Error position doesn't exist
            {

            }

So I thought I'd try something like, this would work great if I could do this

public Sprite(ContentManager content, Rectangle boundry)
            {
                 //load up texture with content and get position
                 Sprite(texture, position, boundry); //<-- Method, delegate or event is expected
            }

Seems the only way I can get around it is to have two constructors that initialize all the same parameters. Except.. if I try this... the base class gets called before I can setup the properties in the inheriting class.

public PlayerCat(ContentManager content, Rectangle deviceBounds)
            : base(deviceBounds, 2, 4, 20)
        {
            //set all my properties
        }

public Sprite(Rectangle deviceBounds)
            : this(deviceBounds, 1, 1, 1)
        {

        }

        public Sprite(Rectangle deviceBounds, int rows, int cols, double framesPerSecond)
        {
            //Properties Error out here because they are called before I get to set them
        }

Upvotes: 0

Views: 1942

Answers (1)

Olivier Jacot-Descombes
Olivier Jacot-Descombes

Reputation: 112447

Move the initialization code to ordinary methods that you call from the constructors. This allows you to call them in any order.

public class Sprite
{
    public Sprite(Texture2D texture, Vector2 position, Rectangle boundry)
        : this(texture, position, boundry, 1, 1, 1)
    {
    }

    public Sprite(Texture2D texture, Vector2 position, Rectangle boundry,
                  int rows, int cols, double framesPerSecond)
    {
        Initialize(texture, position, boundry, rows, cols, framesPerSecond);
    }

    public Sprite(ContentManager content, Rectangle boundry)
    {
         //TODO: Load up texture with content and get position
         Initialize(texture, position, boundry);
    }

    private void Initialize(Texture2D texture, Vector2 position, Rectangle boundry,
                            int rows, int cols, double framesPerSecond)
    {
        //TODO: Set a bunch of properties here        
    }

    private void Initialize(Texture2D texture, Vector2 position, Rectangle boundry)
    {
        Initialize(texture, position, boundry, 2, 2, 14);
    }
}

Upvotes: 1

Related Questions