Non-null objects, the Null Object pattern, and T.init
Meta
jared771 at gmail.com
Fri Jan 17 05:53:13 PST 2014
On Friday, 17 January 2014 at 01:42:38 UTC, Andrei Alexandrescu
wrote:
> Walter and I were talking today about the null pointer issue
> and he had the following idea.
>
> One common idiom to replace null pointer exceptions with milder
> reproducible errors is the null object pattern, i.e. there is
> one object that is used in lieu of the null reference to
> initialize all otherwise uninitialized references. In D that
> would translate naturally to:
>
> class Widget
> {
> private int x;
> private Widget parent;
> this(int y) { x = y; }
> ...
> // Here's the interesting part
> static Widget init = new Widget(42);
> }
>
> Currently the last line doesn't compile, but we can make it
> work if the respective constructor is callable during
> compilation. The compiler will allocate a static buffer for the
> "new"ed Widget object and will make init point there.
>
> Whenever a Widget is to be default-initialized, it will point
> to Widget.init (i.e. it won't be null). This beautifully
> extends the language because currently (with no init
> definition) Widget.init is null.
>
> So the init Widget will satisfy:
>
> assert(x == 42 && parent is Widget.init);
>
> Further avenues are opened by thinking what happens if e.g.
> init is private or @disable-d.
>
> Thoughts?
>
>
> Andrei
Throwing out some more ideas, though non of this compiles right
now (and I managed to make the compiler ICE).
class Widget
{
private int x;
this(int y) { x = y; }
public @property int halfOfX() { return x / 2; }
public void printHello() { std.stdio.writeln("Hello"); }
//Error: 'this' is only defined in non-static member
functions,
//not Widget
static Widget init = new class Widget
{
@disable public override @property int halfOfX();
@disable public override void printHello();
this() { super(int.init); }
};
}
Another idea that unfortunately doesn't work due to the way
static assert works:
class Widget
{
private int x;
this(int y) { x = y; }
public @property int halfOfX() { return x / 2; }
public void printHello() { std.stdio.writeln("Hello"); }
static Widget init = new class Widget
{
//Error: static assert "Tried to access halfOfX
//property of null Widget"
override @property int halfOfX()
{
static assert(false,
"Tried to access halfOfX property of null
Widget");
}
override void printHello()
{
static assert(false,
"Tried to access halfOfX property of null
Widget");
}
this() { super(int.init); }
};
}
Is there any way to get around this?
And then there's this, which causes an ICE:
class Widget
{
private int x;
this(int y) { x = y; }
public @property int halfOfX() { return x / 2; }
public void printHello() { std.stdio.writeln("Hello"); }
static Widget init = new class Widget
{
this()
{
}
};
}
More information about the Digitalmars-d
mailing list