Craig Otis
Craig Otis

Reputation: 32084

Null object pattern in Objective-C

In Java, it is very easy to code the following design:

public abstract class Pizza {
    public static final Pizza.NULL = new Pizza() {
        /* "null" implementations */
    }

    /* actual/abstract implmentations */
}

What is the preferred method to attain the same efficient scenario in Objective-C? I have been unable to find any documentation on the subject, and I have tried a couple different scenarios with static const, #define etc. but none of them seem to work out as well as the Java method above.

I would like to avoid writing a concrete NullPizza class that has a static method to obtain the singleton instance, as it seems more 'proper' for it to be some final property/field of the highest-level interface. (Pizza, in this case.)

Edit: While I understand how the NULL pattern specifically would be handled due to Obj-C's unique method of handling method calls to 'nil', what about other static common instances, such as Response.YES and Response.NO? (See comments for discussion.)

Upvotes: 2

Views: 4099

Answers (4)

Rog
Rog

Reputation: 17170

I don't think there is an easy way to provide this implementation. You're asking for something that is a language feature of Java to be implemented in Objective-C - you can do it but you have to write the code that is in the Java runtime yourself - there is nothing to stop you doing this but it's not something the language has built in.

It's a bit like asking "How do I show a Windows style 'one menu per window" UI in Cocoa' - you can do it but it's not provided for free from the framework. Or, "how can I easily implement Objective-C's nil pointer handling in Java?"

If you really want to see this type of functionality I think you should follow the NSArray/NSMutableArray design pattern. Declare a superclass that can handle all of your special cases:

@interface NullPizza : NSObject
{
}
- (BOOL)areYouANullPizza;
@end

and then subclass with your real Pizza and include a newNullPizza class method (which is just syntax sugar):

@interface Pizza : NullPizza
{
}

+ (Pizza*)Null;
@end

@implementation Pizza
+ (Pizza*)newNullPizza
{
    return [[NullPizza]alloc init]; // Singleton code left as an exercise.
}

- (BOOL)areYouANullPizza;
{
    return NO;
}
@end

Note that if you wanted to implement a +(Pizza*)NULL method on Pizza you should autorelease the new NullPizza you create.

Disclaimer, I typed this code straight into SO. I'd be surprised if it compiles but you get the idea.

Upvotes: 0

JimG
JimG

Reputation: 1782

For your Response.YES and Response.NO, I assume you have instances that you do want to change, rather than just making all Response properties read-only.

A common pattern in Cocoa is to have both immutable and mutable versions of a class (NSArray versus NSMutableArray). For your response example, it would make sense to have an immutable Response class that has the static YES and NO methods, and a MutableResponse subclass that exposes setters for those times where you do want objects to change them. Does this cover your second example?

Upvotes: 0

user23743
user23743

Reputation:

There are two things which can help here. The first is nil, the Objective-C equivalent of the Java NULL pointer - it can actually receive messages and respond to them. It will always return nil if the return value is an object, and 0 if the return value is some primitive type. Therefore if the Null behaviour of your object is "do nothing" you can easily just use nil as the Null value.

The other thing which is helpful is for when you need to store a placeholder or null value in a container object - these usually throw exceptions if you attempt to add nil as a value. Instead you can use the singleton +[NSNull null], which does nothing except act as a "this space intentionally left blank" object.

With these two weapons at your disposal there should be no reason to write a null instance of a custom class :-)

Upvotes: 2

Jason Coco
Jason Coco

Reputation: 78393

There is no need for this type of pattern in Objective-C because it is not considered a runtime error to message a nil instance of a class. If the method has a defined return type, there are defined returns from messaging a nil object (e.g., methods that return an integer return 0 when messaging a nil object).

Upvotes: 12

Related Questions