[英]Ruby: define a class that returns something other than itself when an instance is called without any methods
I'm wondering if there's a way to return an object instead of a string when calling an object without any methods.我想知道在没有任何方法的情况下调用 object 时是否有办法返回 object 而不是字符串。
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 class 以便发生以下情况:
foo = Foo.new
foo #returns @bar
In the specific case I'm interested in I'm using a presenter in a Rails view.在我感兴趣的特定情况下,我在 Rails 视图中使用演示者。 The presenter sets up one main object and then loads a bunch of related content.
演示者设置一个主object,然后加载一堆相关内容。 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:如果我想返回 ExamplePresenter 使用的示例,我可以调用:
@presenter = ExamplePresenter.new(1)
@presenter.example
It would be nice if I could also return the example object by just calling:如果我也可以通过调用返回示例 object 那就太好了:
@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?那么,有没有办法设置默认方法以在调用 object 时返回,例如 to_s 但返回 object 而不是字符串?
If I understand correctly, you want to return the instance of Example
when you call the ExamplePresenter
instance.如果我理解正确,您希望在调用
ExamplePresenter
实例时返回Example
的实例。 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.这种直接机制在任何语言中都不存在,即使存在,它也会阻止对
ExamplePresenter
实例及其方法的所有访问。 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.您可以让
ExamplePresenter
class 将方法委托给其中的Example
实例。 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.实际上,您没有从
@presenter
获得真正的Example
,但您获得了一个ExamplePresenter
,它将所有符合条件的方法传递到其内部Example
,有效地代表它行事。
Some ways of doing this is:这样做的一些方法是:
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.如果
ExamplePresenter
无法响应,这会将任何方法调用传递给内部Example
。 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.请注意,您可能会以这种方式公开超出您想要的内部
Example
,并且无法传递已在ExamplePresenter
上定义的任何方法。
You can use additional logic inside method_missing
to limit exposure or pre/post process the arguments/return values.您可以在
method_missing
中使用其他逻辑来限制暴露或预处理/后处理参数/返回值。
You can define wrapper methods on ExamplePresenter
that do nothing but pass everything to the internal Example
.您可以在
ExamplePresenter
上定义包装器方法,这些方法除了将所有内容传递给内部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.这很快就会变得乏味,但您也可以添加逻辑来更改 arguments,然后再将其传递给
Example
或对结果进行后处理。
You can also mix and match the above two methods也可以混合搭配以上两种方式
There is a library in Ruby stdlib called Delegator built exactly for this purpose. Ruby 标准库中有一个名为Delegator的库,正是为此目的而构建的。 You may look into it.
你可以调查一下。
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如果您确实需要创建
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
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.