Ruby:定义一个类,当在没有任何方法的情况下调用实例时,该类返回除自身以外的其他内容

发布于 2024-11-19 03:07:18 字数 711 浏览 1 评论 0原文

我想知道在没有任何方法的情况下调用对象时是否有办法返回对象而不是字符串。

例如:

class Foo
  def initialize
    @bar = Bar.new
  end
end

有什么方法可以定义 Foo 类,以便发生以下情况:

foo = Foo.new
foo #returns @bar  

在我感兴趣的特定情况下,我在 Rails 视图中使用演示者。演示者设置一个主要对象,然后加载一堆相关内容。重要的部分如下所示:

class ExamplePresenter

  def initialize( id )
    @example = Example.find( id )
  end

  def example
    @example
  end

  ...

end

如果我想返回 ExamplePresenter 使用的示例,我可以调用:

@presenter = ExamplePresenter.new(1)
@presenter.example

如果我也可以通过调用返回示例对象,那就太好了:

@presenter

那么,有没有办法将默认方法设置为调用对象时返回,例如 to_s 但返回对象而不是字符串?

I'm wondering if there's a way to return an object instead of a string when calling an object without any methods.

For instance:

class Foo
  def initialize
    @bar = Bar.new
  end
end

Is there any way to define the Foo class so that the following happens:

foo = Foo.new
foo #returns @bar  

In the specific case I'm interested in I'm using a presenter in a Rails view. The presenter sets up one main object and then loads a bunch of related content. The important part looks like this:

class ExamplePresenter

  def initialize( id )
    @example = Example.find( id )
  end

  def example
    @example
  end

  ...

end

If I want to return the example used by the ExamplePresenter I can call:

@presenter = ExamplePresenter.new(1)
@presenter.example

It would be nice if I could also return the example object by just calling:

@presenter

So, is there a way to set a default method to return when an object is called, like to_s but returning an object instead of a string?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

只为一人 2024-11-26 03:07:18

如果我理解正确的话,当您调用 ExamplePresenter 实例时,您希望返回 Example 的实例。这种直接机制在任何语言中都不存在,即使存在,它也会阻止对 ExamplePresenter 实例及其方法的所有访问。所以这是不符合逻辑的。

不过,您可以做一些事情。您可以将 ExamplePresenter 类委托方法给其中的 Example 实例。实际上,您不会从 @presenter 获得真正的 Example,但您会获得一个 ExamplePresenter,它将所有符合条件的方法传递到其内部 Example< /code> 有效地代表它行事。

执行此操作的一些方法是:

method_missing

class ExamplePresenter
  … # as defined in the question

  def method_missing symbol, *args
    if @example.respond_to?(symbol)
      @example.send(symbol, *args)
    else
      super
    end
  end
end

如果 ExamplePresenter 无法响应,这会将任何方法调用传递给内部 Example。请注意,通过这种方式,您可能会暴露超出您想要的内部 Example 内容,并且 ExamplePresenter 上已定义的任何方法都无法传递。

您可以在 method_missing 中使用其他逻辑来限制暴露或对参数/返回值进行预处理/后处理。

包装器方法

您可以在 ExamplePresenter 上定义包装器方法,这些方法不执行任何操作,只是将所有内容传递给内部 Example。这使您可以明确控制要公开的内容量。

class ExamplePresenter
  … # as before

  def a_method
    @example.a_method
  end
  def another_method(argument, another_argument)
    @example.another_method(argument, another_argument)
  end
end

这很快就会变得乏味,但您也可以在将参数传递给示例或对结果进行后处理之前添加逻辑来更改参数。

您还可以混合搭配以上两种方法

Delegator

Ruby stdlib 中有一个名为 Delegator 正是为此目的而构建的。你可以研究一下。

If I understand correctly, you want to return the instance of Example when you call the ExamplePresenter instance. Such a direct mechanism does not exist in any language, and even if it did, it would block all access to the ExamplePresenter instance and its methods. So it is not logical.

There is something you can do however. You can make the ExamplePresenter class delegate methods to the Example instance inside it. Effectively you do not get a real Example from @presenter but you get an ExamplePresenter that passes all eligible methods into its internal Example effectively acting in behalf of it.

Some ways of doing this is:

method_missing

class ExamplePresenter
  … # as defined in the question

  def method_missing symbol, *args
    if @example.respond_to?(symbol)
      @example.send(symbol, *args)
    else
      super
    end
  end
end

This will pass any method call down to the internal Example if the ExamplePresenter cannot respond to it. Be careful, you may expose more than you want of the internal Example this way, and any method already defined on ExamplePresenter cannot be passed along.

You can use additional logic inside method_missing to limit exposure or pre/post process the arguments/return values.

Wrapper methods

You can define wrapper methods on ExamplePresenter that do nothing but pass everything to the internal Example. This gives you explicit control on how much of it you want to expose.

class ExamplePresenter
  … # as before

  def a_method
    @example.a_method
  end
  def another_method(argument, another_argument)
    @example.another_method(argument, another_argument)
  end
end

This gets tedious fast, but you can also add logic to alter arguments before passing it along to the Example or post process the results.

You can also mix and match the above two methods

Delegator library

There is a library in Ruby stdlib called Delegator built exactly for this purpose. You may look into it.

青芜 2024-11-26 03:07:18

尽管不建议这样做,但您可以这样做:

class Foo
  def self.new
    @bar = Bar.new
  end
end

如果您确实需要创建 Foo 的实例,那么

class << Foo
  alias original_new :new
end

class Foo
  def self.new
    self.original_new # It will not be useful unless you assign this to some variable.
    @bar = Bar.new
  end
end

Although this is not recommended, you can do:

class Foo
  def self.new
    @bar = Bar.new
  end
end

If you actually do need to create an instance of Foo, then

class << Foo
  alias original_new :new
end

class Foo
  def self.new
    self.original_new # It will not be useful unless you assign this to some variable.
    @bar = Bar.new
  end
end
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文