Подтвердить что ты не робот

Почему не могут быть классы внутри методов в Ruby?

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

class A
    def method
        class B
        end
    end
end

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

4b9b3361

Ответ 1

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'

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

Ответ 2

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

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

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"

Ответ 3

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

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, является константой в рубине, в отличие от многих других языков.

Ответ 4

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

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

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

  return anon_obj
end

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