简体   繁体   English

Ruby:定义一个 class,它在没有任何方法调用实例时返回除自身之外的其他内容

[英]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:这样做的一些方法是:

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.如果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中使用其他逻辑来限制暴露或预处理/后处理参数/返回值。

Wrapper methods包装方法

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也可以混合搭配以上两种方式

Delegator library委托人

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.

相关问题 一次定义类和实例方法-Ruby - Define class and instance methods at once - Ruby Ruby / Rails 元编程,如何动态定义实例和 class 方法? - Ruby / Rails meta programing, how to define instance and class methods dynamically? 除了在main中创建对象的实例之外,是否有任何理由在ruby中使用Classname.new关键字 - Is there any reason to use Classname.new keyword in ruby other than when creating an instance of an object in a main 如何在调用类的任何其他方法时调用类的方法(Ruby) - How to call a class's method, when any other method of the class is called (Ruby) (class_eval,define_method)vs(instance_eval,define_method)的Ruby单例方法 - Ruby singleton methods with (class_eval, define_method) vs (instance_eval, define_method) 如何初始化Ruby中当前类以外的实例? - How to initialise an instance other than the current class in Ruby? Ruby 方法没有 class? - Ruby methods without class? 这个ruby属性被称为“ Open Class”吗?这个属性还有其他语言吗? - Is this ruby property called “Open Class”?Is there any other language have this property? 我如何将一个类的实例变量访问到另一个类中的ruby中的其他文件中定义 - how do i access instance variable of one class into other class define in other file in ruby 在Ruby中创建没有实例方法的类 - Create a class with no instance methods in Ruby
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM