Почему в Ruby не может быть классов внутри методов? - PullRequest
12 голосов
/ 07 июля 2010

Могу ли я создать классы Ruby внутри тел функций? Кажется, я получаю сообщение об ошибке, которое говорит мне, что это недопустимо, но я думаю, что так должно быть, поскольку классы здесь слишком объекты.

class A
    def method
        class B
        end
    end
end

Это не с ошибкой 'определение класса внутри тела метода. Если мы не можем, почему мы не можем создавать классы внутри методов?

Ответы [ 4 ]

10 голосов
/ 07 июля 2010

вы можете создавать классы, но вы не можете назначать константы внутри метода.

этот пример работает:

class A
  def a
    b = Class.new
    def b.xxx
      "XXX"
    end
    b
  end
end

a = A.new.a
p a         # #<Class:0x7fa74fe6cc58>
p a.xxx     # "XXX"
8 голосов
/ 07 июля 2010
class A
  def method
    self.class.const_set :B, Class.new {
      def foo
        'bar'
      end
    }
  end
end

A.new.method
A::B.new.foo # => 'bar'

Однако, почему вы хотите назначить константу внутри метода?Это не имеет смысла: константы константы , вы можете назначить их только один раз, что означает, что вы можете запустить свой метод только один раз.Тогда зачем вообще писать метод, если он все равно будет запущен один раз?

8 голосов
/ 07 июля 2010

Вы можете создавать классы из методов и назначать их константе, как показано ниже:

class A
  def create_class class_name
    new_class = Class.new
    new_class.send :define_method, :speak do
      "Hi, There"
    end
    Object.const_set class_name, new_class
  end
end

A.new.create_class "Harry"
h = Harry.new
puts h.speak  # responds => "Hi, There"

потому что имя класса в String в отличие от многих других языков является просто константой в ruby.

4 голосов
/ 07 июля 2010

Речь идет о создании классов, но в комментарии вы говорите о создании анонимных объектов . Не то же самое.

Если вам нужен анонимный объект, вы всегда можете сделать Object.new. Если вам нужен простой похожий на структуру контейнер, вам стоит взглянуть на класс Struct. С его помощью вы можете сделать что-то вроде:

def foo
  anon_obj = Struct.new(:prop1, :prop2).new
  anon_obj.prop1 = 123
  anon_obj.prop2 = 'bar'

  return anon_obj
end

Кстати, Ruby - это язык со строгой типизацией. Но это также динамическая типизация, и вы не можете ожидать, что она будет вести себя как статическая.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...