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