Thread overview
(Maybe) Strange Behaviour of Field Initialization
Apr 28, 2021
eXodiquas
Apr 28, 2021
Adam D. Ruppe
Apr 28, 2021
eXodiquas
April 28, 2021

Hello everyone,

I am playing around with DSFML and drawing some stuff on the screen. It works like a charm but I got some unexpected behavior when building a Particle class.

My class looks like this:

class Particle : Drawable
{
  CircleShape shape = new CircleShape(5);

  this(int x, int y)
  {
    this.shape.position = Vector2f(x, y);
    this.shape.fillColor = Color.Green;
  }

  void draw(RenderTarget renderTarget, RenderStates renderStates) {
    renderTarget.draw(this.shape);
  }
}

When I create an array of Particles and try to draw them, all of them are drawn on the exact same location in my window.

However, when I assign shape in the constructor with this.shape = new CircleShape(5); it works as expected.

The last time I wrote something in D is a few months back, but I cannot remember this behavior. In the code above shape acts like as if it were static without being static, obviously. Is there something wrong with D in this case, or is there something wrong with DSFML or am I just stupid right now and not able to see the obvious.

Thanks in advance.

April 28, 2021

On Wednesday, 28 April 2021 at 15:09:36 UTC, eXodiquas wrote:

>
class Particle : Drawable
{
  CircleShape shape = new CircleShape(5);

This new is actually run at compile time, so every instance of Particle refers to the same instance of CircleShape (unless you rebind it).

>
this.shape.position = Vector2f(x, y);
this.shape.fillColor = Color.Green;

Which means each constructor here overwrites the fields on the same object!

What you probably want is to construct the shape in the constructor too, since that is run for each instance created, instead of just once at compile time and reused for each instance.

This behavior D has is pretty useful... but also pretty surprising to people coming from other languages. I kinda wish the compiler made you be a little more explicit that you actually did intend to compile time construct it.

>

The last time I wrote something in D is a few months back, but I cannot remember this behavior. In the code above shape acts like as if it were static without being static, obviously.

Well, the instance is static, but the handle is not.

If you were to do a this.shape = new Shape; then that object would refer to a new one, but if you don't it all uses the same object.

The code you have is kinda like if you wrote:

static Shape global_shape = (at ctfe) new Shape;

(in the instance) Shape shape = global_shape;

April 28, 2021

On Wednesday, 28 April 2021 at 15:35:57 UTC, Adam D. Ruppe wrote:

>

On Wednesday, 28 April 2021 at 15:09:36 UTC, eXodiquas wrote:

>
class Particle : Drawable
{
  CircleShape shape = new CircleShape(5);

This new is actually run at compile time, so every instance of Particle refers to the same instance of CircleShape (unless you rebind it).

>
this.shape.position = Vector2f(x, y);
this.shape.fillColor = Color.Green;

Which means each constructor here overwrites the fields on the same object!

What you probably want is to construct the shape in the constructor too, since that is run for each instance created, instead of just once at compile time and reused for each instance.

This behavior D has is pretty useful... but also pretty surprising to people coming from other languages. I kinda wish the compiler made you be a little more explicit that you actually did intend to compile time construct it.

>

The last time I wrote something in D is a few months back, but I cannot remember this behavior. In the code above shape acts like as if it were static without being static, obviously.

Well, the instance is static, but the handle is not.

If you were to do a this.shape = new Shape; then that object would refer to a new one, but if you don't it all uses the same object.

The code you have is kinda like if you wrote:

static Shape global_shape = (at ctfe) new Shape;

(in the instance) Shape shape = global_shape;

Thanks, this is a pretty good explanation. I get it now. :)

This behavior sounds pretty neat, as long as you know about it. :P