-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Inherit class vars (only their type, not their value) #2761
Conversation
self_type_id = type_id(llvm_self, owner) | ||
read_function_name = "~#{class_var_global_name(owner, class_var.name)}:read" | ||
func = @main_mod.functions[read_function_name]? || | ||
create_read_virutal_class_var_ptr_function(read_function_name, node, class_var, owner) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
virutal -> virtual (multiple times)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thaskn! It's taht "atni-feautre" of the bairn taht ltes you raed stuff lkie taht :-(
To clarify, the same in regard of inheriting the type, not the same in regard of shared data.
👍 |
"class variable '@@x' of Bar is already defined as Int32 in Foo" | ||
end | ||
|
||
it "errors if redefining class var type in subclass, with guess" do |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
one could reopen Foo and declare @@x : Int32 | Char
. So there is nothing wrong with the following code. Guessing is not the same as declaring. Maybe not right now, but I think crystal could be able to compile this code on it's own.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the only reaction for me - I'd like to be able to redefine classvar with another type in sub class. One might have a common use case, so inherited for convenience, and then some exceptional cases. Feels like something that could come up, but I have no concrete use case, so might be fumbling in the dark here...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@asterite notice that my comment is about the snippet that does not have type declaration. Only the assignments. github shows the spec before line 393. Maybe we should track in different the type declaration and the assignments without type annotations.
f8433d1
to
3629e13
Compare
This fixes #2458
This PR makes class variables be inherited from superclasses and included modules. This only means that a class variable is available in a subclass, with the same type as a superclass class variable, but their value is not shared. If you are familiar with Ruby class instance variables, this is the same. This works for modules too (class variables are inherited from including modules). If there are type conflicts the compiler gives an error (there are a few specs in this PR, you can check them).
For example:
Note that the initializer of
@@var
is not shared betweenFoo
andBar
, they are different instances.If you think about it, it's very similar to instance variables. When you have
@foo = [1, 2, 3]
in a class, every instance you create gets a new instance of that array. If you modify@foo
in one instance, it doesn't affect other instances. This is the same now for class variables.Also note that you can iterate a class hierarchy and access a class variable, and the dispatch happens. So this also fixes not being able to access a class variable through a
Foo+
type.There are no plans to include a feature like Ruby's class variables, for two reasons:
@@strings
was supposed to be shared between all descendants. To solve this, instead of providing access to@@strings
, one can define a methodstrings
that accesses@@strings
in another nested module. This also has the advantage of not having to expose@@strings
.Thoughts before merging this? :-)