Redefining “class” keyword in Ruby

2019-09-24 16:18发布

问题:

To define a class I must do the following (for example)

class Foo
   #attr_accessors
   #methods
   #so on
end
foo = Foo.new #to create an instance

Problem

I need to achieve the following

case_class Foo_inmutable #I change class for case_class
   #attr_accessors
   #methods
   #so on
end
foo_inmutable = Foo_inmutable.new 
#->SyntaxError: uninitialze constant Foo_inmutable

I need the ruby interpreter to treat the case_class the same way to keyword class

回答1:

Like almost all programming languages, Ruby does not allow you to modify its syntax or semantics. So, what you want is not possible.

You can, however, quite easily write a method that accomplishes your goal, but without changing the syntax and semantics of Ruby:

class Module
  def case_class(name, superclass = ::Object, &blk)
    const_set(name, Class.new(superclass, &blk))
  end
end

def case_class(name, superclass = ::Object, &blk)
  self.class.case_class(name, superclass, &blk)
end

case_class :Foo_immutable do
#          ↑              ↑↑
# these are the only differences to your proposed syntax

  #attr_accessors
  #methods
  #so on
end

foo_immutable = Foo_immutable.new


回答2:

To achieve this, besides defining what's already been said in the previous answer:

class Module
  def case_class(name, superclass = ::Object, &blk)
    const_set(name, Class.new(superclass, &blk))
  end
end

def case_class(name, superclass = ::Object, &blk)
  self.class.case_class(name, superclass, &blk)
end

You may want to have a look at the const_missing method, and the "Lookup" that ruby does for constants inside the various scopes

That will allow you to do stuff like

case_class Foo do
...
end

For further explanation you can refer to this page: tadp-utn-frba.github.io

It has tons of useful scripts explaining ruby metaprogramming (in spanish) and how to achieve what you are looking for, also it has contact references for the people in charge of the page, so you can email them at any time (Given you are a student of the class) for academic reasons.

Cheers!