Content deleted Content added
m Disambiguating links to Object-orientation (link changed to Object-oriented programming) using DisamAssist. |
|||
(27 intermediate revisions by 19 users not shown) | |||
Line 1:
{{Short description|Object with no referenced value or with defined neutral ("null") behavior}}
{{Redirect|Null object|the concept in category theory|Initial object}}
In [[Object-oriented programming|object-oriented]] [[computer programming]], a '''null object''' is an [[Object (computer science)|object]] with no referenced value or with defined neutral (
| first = Thomas
| last = Kühne
| contribution = Void Value
| title = Proceedings of the First International Conference on Object-Oriented Technology, White Object-Oriented Nights 1996 (WOON'96), St. Petersburg, Russia
| year = 1996
}}</ref>
and later in the [[Pattern Languages of Programs#Publications|''Pattern Languages of Program Design'' book series]] as "Null Object".<ref>{{Cite book
| first = Bobby
| last = Woolf
Line 21 ⟶ 29:
== Description ==
{{Unreferenced section|date=June 2023}}
Instead of using a [[null reference]] to convey the absence of an object (for instance, a non-existent customer), one uses an object which implements the expected [[Interface_(computing)#In_object-oriented_languages | interface]], but whose method body is empty.
One advantage of this approach over a working default implementation is that a null object is very predictable and has no side effects: it does ''nothing''.
For example, a function may retrieve a list of files in a folder and perform some action on each. In the case of an empty folder, one response may be to throw an exception or return a null reference rather than a list. Thus, the code
By returning a null object (i.e., an empty list) instead, there is no need to verify that the return value is in fact a list. The calling function may simply iterate the list as normal, effectively doing nothing. It is, however, still possible to check whether the return value is a null object (an empty list) and react differently if desired.
Line 67 ⟶ 77:
}
This separates normal logic from special case handling
==Relation to other patterns==
It can be regarded as a special case of the [[State pattern]] and the [[Strategy pattern]].
It is not a pattern from ''[[
| first = Martin
| last = Fowler
Line 127 ⟶ 137:
===Extension methods and Null coalescing===
{{Unreferenced section|date=June 2023}}
In some [[Microsoft .NET]] languages, [[Extension method]]s can be used to perform what is called 'null coalescing'. This is because extension methods can be called on null values as if it concerns an 'instance method invocation' while in fact extension methods are static. Extension methods can be made to check for null values, thereby freeing code that uses them from ever having to do so. Note that the example below uses the [[C Sharp (programming language)|C#]] [[Null coalescing operator]] to guarantee error free invocation, where it could also have used a more mundane if...then...else. The following example only works when you do not care the existence of null, or you treat null and empty string the same. The assumption may not hold in other applications.
Line 162 ⟶ 173:
<syntaxhighlight lang="cpp">
import std;
class Animal {
Line 171 ⟶ 182:
};
class Dog
public:
virtual void MakeSound() const override { std::
};
class NullAnimal
public:
virtual void MakeSound() const override {}
Line 266 ⟶ 277:
Following the Smalltalk principle, ''everything is an object'', the absence of an object is itself modeled by an object, called <code>nil</code>. In the GNU Smalltalk for example, the class of <code>nil</code> is <code>UndefinedObject</code>, a direct descendant of <code>Object</code>.
Any operation that fails to return a sensible object for its purpose may return <code>nil</code> instead, thus avoiding the special case of returning "no object" unsupported by Smalltalk designers. This method has the advantage of simplicity (no need for a special case) over the classical "null" or "no object" or "null reference" approach. Especially useful messages to be used with <code>nil</code> are <code>isNil</code>, <code>ifNil:</code> or <code>ifNotNil:</code>
===Common Lisp===
Line 302 ⟶ 313:
Unlike Common Lisp, and many dialects of Lisp, the Scheme dialect does not have a nil value which works this way; the functions <code>car</code> and <code>cdr</code> may not be applied to an empty list; Scheme application code therefore has to use the <code>empty?</code> or <code>pair?</code> predicate functions to sidestep this situation, even in situations where very similar Lisp would not need to distinguish the empty and non-empty cases thanks to the behavior of <code>nil</code>.
===
In [[Duck typing|duck-typed]] languages like [[Ruby (programming language)|Ruby]], language inheritance is not necessary to provide expected behavior.
Line 325 ⟶ 336:
=> nil
</syntaxhighlight>
Attempts to directly [[
===
In [[Duck typing|duck-typed]] languages like [[JavaScript]], language inheritance is not necessary to provide expected behavior.
<syntaxhighlight lang="javascript">
Line 354 ⟶ 365:
<syntaxhighlight lang="java">
public interface Animal {
void makeSound()
}
Line 365 ⟶ 376:
public class NullAnimal implements Animal {
public void makeSound() {
}
}
Line 384 ⟶ 395:
{
public function makeSound()
{
echo "Woof...\n";
}
}
Line 392 ⟶ 403:
{
public function makeSound()
{
echo "Meowww...\n";
}
}
Line 400 ⟶ 411:
{
public function makeSound()
{
// silence...
}
Line 406 ⟶ 417:
$animalType = 'elephant';
switch($animalType) {▼
function makeAnimalFromAnimalType(string $animalType): Animal
{
$animal = new Dog();▼
▲ switch ($animalType) {
case '
return new Cat();
}
}
function animalMakeSound(Animal $animal): void
{
}
foreach ([
makeAnimalFromAnimalType('dog'),
makeAnimalFromAnimalType('NullAnimal'),
makeAnimalFromAnimalType('cat'),
] as $animal) {
// That's also reduce null handling code
animalMakeSound($animal);
}
▲$animal->makeSound(); // ..the null animal makes no sound
</syntaxhighlight>
Line 423 ⟶ 450:
The following null object pattern implementation demonstrates the concrete class providing its corresponding null object in a static field <code>Empty</code>. This approach is frequently used in the .NET Framework (<code>String.Empty</code>, <code>EventArgs.Empty</code>, <code>Guid.Empty</code>, etc.).
<syntaxhighlight lang="
Public Class Animal
Public Shared ReadOnly Empty As Animal = New AnimalEmpty()
Line 442 ⟶ 469:
==Criticism==
This pattern should be used carefully, as it can make errors/bugs appear as normal program execution.<ref>Fowler, Martin (1999). Refactoring,
Care should be taken not to implement this pattern just to avoid null checks and make code more readable, since the harder-to-read code may just move to another place and be less standard—such as when different logic must execute in case the object provided is indeed the null object. The common pattern in most languages with [[reference type]]s is to compare a reference to a single value referred to as null or nil. Also, there is an additional need for testing that no code anywhere ever assigns null instead of the null object, because in most cases and languages with static typing, this is not a compiler error if the null object is of a reference type, although it would certainly lead to errors at run time in parts of the code where the pattern was used to avoid null checks. On top of that, in most languages and assuming there can be many null objects (i.e., the null object is a reference type but doesn't implement the [[singleton pattern]] in one or another way), checking for the null object instead of for the null or nil value introduces overhead, as does the singleton pattern likely itself upon obtaining the singleton reference.
==See also==
Line 454 ⟶ 481:
==External links==
*[http://www.cs.oberlin.edu/~jwalker/nullObjPattern/
*[http://martinfowler.com/eaaCatalog/specialCase.html Martin Fowler's description of Special Case, a slightly more general pattern]
*[http://www.owlnet.rice.edu/~comp212/00-spring/handouts/week06/null_object_revisited.htm Null Object Pattern Revisited]
|