goby-lang / goby

Goby - Yet another programming language written in Go
MIT License
3.49k stars 171 forks source link

Question: class can inherit module? #119

Closed hachi8833 closed 7 years ago

hachi8833 commented 7 years ago

I have a small question.

I found you can inherit modules to class as if modules were a class.

The following works on the latest Goby build, but I just wonder if this behavior is OK.

module Foo
  def self.my
    999
  end
  def ten
    100
  end
  def five
     7
  end
end

class Bar < Foo
  def five
    5
  end
end

a = Bar.new
puts(a.ten * a.five ) # => 500
puts(Bar::Foo.my)  # => 999

If you run the code with Ruby, you receive "superclass must be a Class (Module given) (TypeError)." If you change module to class in line 1, it works with Ruby.

hachi8833 commented 7 years ago

One more question. Are the embedded classes closed?

Looks like the embedded classes are not extensible so far: I cannot add or override methods against them, and cannot inherit them.

class String
  def my_method
    self + "47"
  end
end

a = "test"
puts(a.my_method)  # => undefined method `my_method' for 1
class MyString < String
  def my_method
    self + "47"
  end
end

i = MyString.new("string")
puts(i.my_method)  # => Constant String is not a class. got=CLASS

The codes above work on Ruby 2.4.

I'm just unsure if this behavior is the expected one, or unimplemented. This depends on your plan or specification.

adlerhsieh commented 7 years ago

I don't think we have implemented self-defined method for built-in class, so defining extra methods for String is not working. And yes, from a design perspective a module should not be inherited to a class. It would be great to implement those features if you like to try :)

adlerhsieh commented 7 years ago

Unless @st0012 got a different idea on this

hachi8833 commented 7 years ago

Thank you for the answer!

FYI: now I found that built-in class can be extended and overload methods by including a module:

module MyModule
  def my_method
    "47"
  end

  def to_i
    48
  end
end

class String
  include(MyModule)
end

i = String.new("string")
puts(i.my_method)  # => 47
puts(i.to_i)       # => 48

In Ruby, puts(i.to_i) returns 0.


Just a mutter to myself: Module's behavior is a little bit different between current Goby and Ruby, but this implies that built-in classes could be extended with modules that are written in Goby.

(Actually, I've been wondering if built-in classes such as Array and Hash can be extended with Enumerable module written in Goby, which might make Goby extensible more easily. To do this, perhaps I need a built-in Enumerator class first :-p. )

st0012 commented 7 years ago

@hachi8833 @adlerhsieh I am not intended to make module inheritable, I just haven't forbidden such usage (please send a PR if you want to fix this). I also don't want built in classes to be extended, just haven't deal with it yet. And thanks for the report, you really found some interesting behaviors I didn't expect.

hachi8833 commented 7 years ago

Thank you for the answer! I just wanted to check your plans and intentions for modules and classes before touching codes.

st0012 commented 7 years ago

@hachi8833 Do you want to fix this as your first contribution 😁?

hachi8833 commented 7 years ago

Thnx! I'd dig it if I could fix the one.

To fix: modules should not be inherited to class with < operator on class definition. (I'd notify that I'm slow in writing codes ;-)

st0012 commented 7 years ago

You should do this on the vm side and RClass struct has a flag determine if it's a module. So you just have to find a place to block the inheritance.

hachi8833 commented 7 years ago

131 under construction might be the key for the fix.

st0012 commented 7 years ago

I think this check should happen on vm side, cause in the future I might remove module statement and use class statement for module too. And if we want to prevent this in the parsing process, we can already do that.

st0012 commented 7 years ago

Thanks for @hachi8833 this has been fixed 😄