N
Noah Roberts
Phlip said:You made 3 up.
Really? Tell me then, what does the following code do?
class T
{
int * x;
public:
T() : x(0) {}
T(int v) : x(new int(x)) {}
void op() {*x = 0;}
};
class TNull : public T
{
public:
void op() {}
};
T * whatever() { return new TNull(); }
int main()
{
T * t = whatever();
t->op();
return 0;
}
If I just made #3 up then that code works, right? No undefined
behavior? Look again...you sure that your method of implementing null
object doesn't require polymorphic classes?
Look also at the problem implementing NullObject as a subclass of your
concrete object. What business does TNull have with an x? Does it
need it? Should it be there? Is TNull a T?
Simple piss poor setup yes, but it illustrates some of the problems.
What if op() did more than access a pointer? Since TNull is supposed
to represent an invalid T then how could anything performed by op() be
valid?
Refactoring works...at least in my experience. But you need to keep
certain details in mind. For instance that nullObject as shown in that
design *requires* polymorphic objects. Refactoring, like anything, can
be taken too far and you need to think about how the designs apply to
the language you are using to establish when, and when not, to use them.