Last update March 29, 2005

Null Object



See WardsWiki:NullObject

Comments

EricAnderton:

I've done some private research into Null Objects under C++. The general idea, if I'm not mistaken, is to have an immutable singleton that will not disrupt the flow of code if used like a real object, yet can be tested for identity.

In essence, all the worries of using a null pointer as a valid reference become irrelevant, but you still keep the usefulness of testing a reference for null.

D lacks native support for something like this, but well-written code can emulate the feature just as well.

public class MyClass{
    /* class methods */
    void foo(){}

    /* null singleton */
    public static MyClass Null;
}

private class __MyClassNull: MyClass{
    /* override *every* single method in MyClass with boilerplate code that does nothing */
    override void foo(){}
)

/* set the singleton null instance */
static this(){ MyClass.Null = new __MyClassNull(); }

void main(){
    MyClass mc = MyClass.Null;  // assignment
    if(mc == MyClass.Null); // comparison
    mc.foo(); // doesn't throw an exception, even if we're 'null'
}

What you loose, is a single, system-wide value that can be used for null: every type now has it's own version. This isn't necessarily a drawback, but without proper language support it can be a bit bothersome to track. For example, polymorphism makes it difficult to compare a casted type to a null value.

// using the above code
class MyOtherClass: MyClass{
    static MyOtherClass Null;
}
private class __MyOtherClassNull: MyOtherClass {)
static this(){ MyOtherClass.Null = new __MyOtherClassNull(); }

void failure(){
    MyClass mc = MyOtherClass.Null;
    if(mc == MyClass.Null); // returns false, even though we set this one to 'null'
}

.. there are ways around this, but they widen the difference between 'null' and the Null identity.

Also, D's template system simply isn't powerful enough to create the needed boilerplate code for an arbitrary interface, so a code generator is the only way to avoid coding 'null objects' by hand.

Overall, it is a useful technique that can save lots of CPU time in cases where comparsions against null are made frequently. Typically, this is in a map where keys-value pairs are frequently modified to key-null pairs, and vice-versa.

D could use such a feature, but without it being directly built-in and enshrined in the language itself, I'm at a loss as how to hook it in. Making the .init property writable for user types might be a good half-step towoard accomplishing this. Adding a writable .null property to user types would also be a huge plus.

// using the above code
static this(){
    MyClass.init = MyClass.Null;
    MyClass.null = MyClass.Null;
}

... which would improve things a little, but it still burdens the developer with issues regarding multiple 'null' identities in a class hierarchy.

FrontPage | News | TestPage | MessageBoard | Search | Contributors | Folders | Index | Help | Preferences | Edit

Edit text of this page (date of last change: March 29, 2005 4:43 (diff))