I'm puzzled:
-----------------------
class X
A = 1
def X.a
A
end
end
class Y < X
A = 2
end
class Z < X
A = 3
def Z.a
A
end
end
p X.a #=> 1
p Y.a #=> 1
p Z.a #=> 3
-----------------------
(ruby 1.8.2 (2004-12-25) [i386-mswin32])
Shouldn't this yield at least a warning?
Is this a feature?
Since A is not a class variable (it's a local variable) it's saved in "X.a" closure. In Y class it doesn't exist, so it can't influence on "X.a" method.
PS I hope my crappy english doesn't mess things too much.
I'm puzzled:
-----------------------
class X
A = 1
def X.a
A
end
end
class Y < X
A = 2
end
class Z < X
A = 3
def Z.a
A
end
end
p X.a #=> 1
p Y.a #=> 1
p Z.a #=> 3
-----------------------
(ruby 1.8.2 (2004-12-25) [i386-mswin32])
Shouldn't this yield at least a warning?
Is this a feature?
Since A is not a class variable (it's a local variable) it's saved in "X.a" closure. In Y class it doesn't exist, so it can't influence on "X.a" method.
Actually A is a constant, not a local variable, and method definitions
aren't closures. I'm pretty sure that what's happening is that the
constant references are being resolved at compile-time, so that by the time
Y.a is run, the reference inside X.a has been permanently resolved to
X::A.
See what happens when you make this change:
def X.a
const_get("A")
end
Now the constant is being resolved dynamically, and you'll get 1/2/3
in the output.
I'm puzzled:
-----------------------
class X
A = 1
def X.a
A
end
end
class Y < X
A = 2
end
class Z < X
A = 3
def Z.a
A
end
end
p X.a #=> 1
p Y.a #=> 1
p Z.a #=> 3
-----------------------
(ruby 1.8.2 (2004-12-25) [i386-mswin32])
Shouldn't this yield at least a warning?
Is this a feature?
Since A is not a class variable (it's a local variable) it's saved in "X.a" closure. In Y class it doesn't exist, so it can't influence on "X.a" method.
PS I hope my crappy english doesn't mess things too much.
Ooops... sorry.. Didn't get you right.
Indeed, seems like a bug with constants assignment.
class X
A = 1
end
class Y < X
A = 2
end
class Z < X
end
X.constants => 'A'
Y.constants => 'A'
Z.constants => 'A' # Z inherits constants from its parent
X::A = 3
Z::A => 3 # changes in superclass populated to subclasses
Z::A = 4
X::A => 3 # changes in subclass remains local to subclass
Seems like assignments are made without lookup in superclasses.
aren't closures. I'm pretty sure that what's happening is that the
constant references are being resolved at compile-time, so that by the time
Y.a is run, the reference inside X.a has been permanently resolved to
X::A.
Well not really : ruby *want* that you think that the constants are resolved
statically
[ruby-talk:32774]
"Those rules provide you the "illusion" of statically scoped constants."
Indeed, seems like a bug with constants assignment.
class X
A = 1
end
class Y < X
A = 2
end
class Z < X
end
X.constants => 'A'
Y.constants => 'A'
Z.constants => 'A' # Z inherits constants from its parent
X::A = 3
Z::A => 3 # changes in superclass populated to subclasses
Z::A = 4
X::A => 3 # changes in subclass remains local to subclass
Seems like assignments are made without lookup in superclasses.
There's no bug. There's a lookup path for constants. Z finds X::A on
its lookup path. You could also do: Z::String and although you'd get
a warning, Ruby would indeed return the top-level constant String
(because there's no other String to replace it in the lookup path).
When you change X::A (aside from getting a warning it's not
exactly that the change is propagated to Z. Rather, the change
affects a constant that is on Z's lookup path -- so, naturally, when Z
sees that constant, it's changed. It's not because Z is a subclass of
X. The change to X::A would be visible from anywhere.
When you assign to Z::A, you're creating a new constant. This has no
effect on X::A; the two are completely unrelated.
[...] Actually A is a constant, not a local variable, and method definitions
aren't closures. I'm pretty sure that what's happening is that the
constant references are being resolved at compile-time, so that by the time
Y.a is run, the reference inside X.a has been permanently resolved to
X::A.
See what happens when you make this change:
def X.a
const_get("A")
end
Now the constant is being resolved dynamically, and you'll get 1/2/3
in the output.
erm, yes.
true, but i think this makes it entirely weird.
so i call Y: self is Y, there is an A in Y but the A from X is used, right?
if i redefine X.a to
def X.a
self::A
end
it's like i would expect it.
Ok, as this looks still completely odd to me (whatelse if not self would do as an implicit target?) there has to be a real good reason why it is this way, right? RIGHT?
(i don't have to call self.const_get(:A), why do i have to use self::A to get the A from self?)
> aren't closures. I'm pretty sure that what's happening is that the
> constant references are being resolved at compile-time, so that by the time
> Y.a is run, the reference inside X.a has been permanently resolved to
> X::A.
Well not really : ruby *want* that you think that the constants are resolved
statically
[ruby-talk:32774]
"Those rules provide you the "illusion" of statically scoped constants."
Darn, I thought that by avoiding the word "statically" I was safe