Not sure if this is a bug or I missed something in the docs.
I can't seem to get the compiler to honor inheritance where the method is mutable in nature. Rather than cut-and-paste my convoluted code, I wrote a simpler demo:
type
Pet = ref object of RootObj
age*: int
Dog = ref object of Pet
fur_color*: string
method say_age(p: Pet): void {.base.} =
echo "pet is aged " & $p.age
method get_older(p: var Pet): void {.base.} =
p.age = p.age + 1
var
polly = Pet()
sparky = Dog()
polly.age = 3
sparky.age = 2
polly.say_age()
sparky.say_age()
polly.get_older()
sparky.get_older()
The say_age method worked just fine. The method works for both Pet and Dog. However, I get a compiler error for get_older:
test.nim(26, 7) Error: type mismatch: got <Dog>
but expected one of:
method get_older(p: var Pet): void
expression: get_older(sparky)
I'm running 0.18.10.
by the way you should probably use:
method get_older(p: Pet): void {.base.} =
p.age = p.age + 1
without the var.
The understanding is that for ref object var applies to the "ref", not the data. Here is it in picture:
## Stack object
Proc ------> var memory
## Ref object
Proc ------> var reference to memory location -----------> memory
In the first case, "normal object" you cannot modify the memory without var.
In the second case, you cannot modify the pointer to the memory, i.e. assign a completely new pet.
But, you can modify what is at the memory pointed to. This is similar to const pointer in C, you cannot change the address pointed to, but you can change what is stored at that address. It's shallow immutability (just one level).
@mratsim,
That fixed it. Makes sense. In fact, is it generally correct to say:
but
And the same can be said about the 'var' prefix in parameters? It is a distinctions of "always" vs. "sometimes"?
I get the impression this is true, but I've not dove into the compiler enough to know if actually true.