【问题标题】:Why cant there be classes inside methods in Ruby?为什么 Ruby 的方法中不能有类?
【发布时间】:2011-03-12 18:41:27
【问题描述】:

我可以在函数体中创建 Ruby 类吗? 我似乎收到了错误,告诉我它是不允许的,但我认为这应该是因为这里的类太对象了。

A级 定义方法 B类 结尾 结尾 结束

这会失败,并在方法体中出现错误“类定义”。 如果我们不能,为什么我们不能在方法中创建类?

【问题讨论】:

  • 你为什么要这样做?
  • @Mark - 我一直在用 C# 中的匿名对象来做这件事。诚然,它们本身没有方法,但这仍然是想要动态创建类的正当理由。一个短暂的容器对象来临时保存一些我可以以强类型方式使用的数据(至少通过名称引用属性)是一个非常方便的东西。
  • @Mark- 正如 tvanfosson 所说!
  • 有条件地对类进行猴子补丁也很有用。
  • @MarkElliot 在测试中,例如。此外,某些核心开发人员出于某种原因创建了此错误条件,它可能是允许的,直到有人明确禁止。

标签: ruby


【解决方案1】:

您可以创建类,但不能从方法内部分配常量。

这个例子有效:

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"

【讨论】:

  • 这是一个更好的答案。 OP 想知道为什么。你已经解释了原因。
  • 他的问题是关于在方法中定义一个类,而不是实例化一个。这个答案没有解决这个问题。
【解决方案2】:

您可以在方法中创建类并将它们分配给一个常量,如下所示

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​​ 中的常量。

【讨论】:

    【解决方案3】:
    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'
    

    但是,为什么要在方法中分配一个常量呢?这没有任何意义:常量是常量,你只能分配给它们一次,这意味着你只能运行你的方法一次。那么,你为什么要编写一个方法,如果它只运行一次呢?

    【讨论】:

    • 我可以想到几种模式,可以想象在方法中定义类,最值得注意的是桥、适配器和工厂。如果您需要获取一些静态资源(例如 LDAP 连接),但您不想指定实现(例如 net/ldap 与 ruby​​-net-ldap),这将很有用。不过,它远非日常需要。
    • 我希望类是本地的动作实例。这样一旦动作完成,类实例就注定要被垃圾回收。即,我做肥皂请求,将其解析为某个类的实例(以便它们回复某些调用)。并将@things 传递给视图。一旦视图被渲染,我根本不想记住@things
    【解决方案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
    

    顺便说一句,Ruby 一种强类型语言。但它也是一个动态类型,你不能指望它表现得像静态类型。

    【讨论】:

      猜你喜欢
      • 2021-07-20
      • 1970-01-01
      • 1970-01-01
      • 2014-08-24
      • 2014-08-26
      • 1970-01-01
      • 2012-09-08
      • 2013-08-30
      • 1970-01-01
      相关资源
      最近更新 更多