# Why can't redefine #nil? method on a user defined Object?

**URL:** <https://forum.crystal-lang.org/t/why-cant-redefine-nil-method-on-a-user-defined-object/4860>\
**Category:** Help & Support\
**Created:** [August 16, 2022, 8:31am UTC](https://forum.crystal-lang.org/t/why-cant-redefine-nil-method-on-a-user-defined-object/4860 "2022-08-16T08:31:36Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![zw963](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/zw963/32/1623_2.png) [@zw963](https://forum.crystal-lang.org/u/zw963)\
**Post date:** [August 16, 2022, 8:31am UTC](https://forum.crystal-lang.org/t/why-cant-redefine-nil-method-on-a-user-defined-object/4860/1 "2022-08-16T08:31:36Z")

</div>

Following is a real use case.

I create a tiny shard([hashr](https://github.com/zw963/hashr)) for makes test on JSON response easier, following is my spec.

> <https://github.com/zw963/hashr/blob/v0.1.0/spec/hashr_spec.cr#L29-L30>

Following is a more simple example:

```crystal
h = {"nilValue" => nil}.to_json
value = Hashr.new({"foo" => JSON.parse(h)})

value.foo.nilValue.should eq nil # => true
value.foo.nilValue.should be_nil # => false, because i can't redefine Hashr#nil? method

```

I expect can test with nil value use `be_nil` instead of `eq nil`, but, it not work, because Crystal prevent me define `#nil?` on Hashr object.

```auto
In src/hashr.cr:21:7

 21 | def nil?
          ^
Error: 'nil?' is a pseudo-method and can't be redefined

```

How to workaround on this?

Thank you.

---

<div class="post-metadata">

**Author:** ![straight-shoota](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/straight-shoota/32/36_2.png) [@straight-shoota](https://forum.crystal-lang.org/u/straight-shoota)\
**Post date:** [August 16, 2022, 12:24pm UTC](https://forum.crystal-lang.org/t/why-cant-redefine-nil-method-on-a-user-defined-object/4860/2 "2022-08-16T12:24:11Z")

</div>

There is no workaround. `nil` is a special value in Crystal. The compiler can’t allow any other value to pose as nil with returning true for `#nil?`. Else the type system would break.

So you can’t have your return value fulfill a `be_nil` expectation. `be_nil` is essentially a type check like `be_a(Nil)` which an object of type `Hashr` can’t satisfy.

The same applies to `JSON::Any` wrapping a `nil` value, btw.

---

<div class="post-metadata">

**Author:** ![asterite](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/asterite/32/60_2.png) [@asterite](https://forum.crystal-lang.org/u/asterite)\
**Post date:** [August 16, 2022, 1:10pm UTC](https://forum.crystal-lang.org/t/why-cant-redefine-nil-method-on-a-user-defined-object/4860/3 "2022-08-16T13:10:08Z")

</div>

To clarify a bit.

Let’s say you have this code:

```crystal
x = rand < 0.5 ? 1 : nil
# Here x is of type (Int32 | Nil)

if x.nil?
  # Here x is guaranteed to be Nil
else
  puts x + 2 # This works because the compiler knows this can't be Nil
end

```

If you were allowed to redefine `nil?` and return `true` for something that’s actually not exactly `Nil`, the above guarantees don’t hold anymore.
