Skip to content
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

Class methods can't be included from modules #7927

Closed
malte-v opened this issue Jun 27, 2019 · 10 comments
Closed

Class methods can't be included from modules #7927

malte-v opened this issue Jun 27, 2019 · 10 comments

Comments

@malte-v
Copy link
Contributor

malte-v commented Jun 27, 2019

For some reason class methods can't be included from modules:

module Bar
  def self.bar
  end
end

class Foo
  include Bar
end

Foo.bar # undefined method 'bar' for Foo.class

Is this the desired behaviour? If so, why isn't this allowed?

@yxhuvud
Copy link
Contributor

yxhuvud commented Jun 27, 2019

This behaviour is copied without modification (as far as I know) from Ruby. I'm not certain it is optimal though - I wouldn't really mind having module behave like Rails concerns (which is one way to handle it).

But to actually answer your question, you can create a module like

module Bar
  def bar
  end
end

and then use the extend keyword to add the methods as class methods.

EDIT: Fix typo, that @malte-v pointed out

@malte-v
Copy link
Contributor Author

malte-v commented Jun 27, 2019

If you want to use extend, the module methods need to be instance methods. Class methods aren't copied over by extend.

@asterite
Copy link
Member

This works exactly like in Ruby though I always wondered whether only include should exist in the language (though one use case of extend in the standard library is ENV extends Enumerable, but that could always be something like ENV = Env.new and making Env include Enumerable).

It would also simplify the language a bit.

@malte-v
Copy link
Contributor Author

malte-v commented Jun 27, 2019

I'm in favor of removing extend and letting include copy class methods and variables. I don't think Crystal needs to be exactly like Ruby, especially when it comes to the not-so-great parts of Ruby.

@girng
Copy link
Contributor

girng commented Jun 27, 2019

including modules inside classes to now shadow-act as a class method (when it's really a method from a module) is confusing, concealing, less explicit, and probably more prone to bugs

the compiler is doing us a favor by showing this error

@malte-v
Copy link
Contributor Author

malte-v commented Jun 27, 2019

@girng Can you clarify why this would be confusing? Modules can also have class methods and variables.

@malte-v
Copy link
Contributor Author

malte-v commented Jun 27, 2019

One major thing to consider when removing extend: What about extend self? Maybe add a new namespace keyword?

@girng
Copy link
Contributor

girng commented Jun 27, 2019

@malte-v Not sure, but off the top of my head, if a developer is looking for included methods in a class, they are going to be looking for methods under a class, not a module

@asterite
Copy link
Member

extend self is just adding self. to each method. We have a similar thing with private and protected: you have to add those to each method. So living without extend self isn't a really big deal, I think.

@asterite
Copy link
Member

I'm going to close this because this is working as expected, at least with the current semantics. Maybe in the future we'll change them but it's independent of this issue being open.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants