在类方法中使用实例变量 - Ruby

发布于 2025-01-05 19:43:06 字数 291 浏览 0 评论 0原文

我有一个类似下面的类,我使用实例变量(数组)来避免使用大量方法参数。

它按我的预期工作,但这是一个好的做法吗? 实际上我不希望这有效,但我猜类方法在其他语言中不能像静态方法一样工作。

class DummyClass
  def self.dummy_method1
    @arr = []
    # Play with that array
  end

  def self.dummy_method2
    # use @arr for something else
  end
end

I have a class something like below, and I used instance variables (array) to avoid using lots of method parameters.

It works as I expected but is that a good practice?
Actually I wouldn't expect that worked, but I guess class methods are not working as static methods in other languages.

class DummyClass
  def self.dummy_method1
    @arr = []
    # Play with that array
  end

  def self.dummy_method2
    # use @arr for something else
  end
end

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

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

发布评论

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

评论(2

梦里°也失望 2025-01-12 19:43:06

实例变量作用于 Ruby 中的类的原因是 Ruby 类本身就是实例(类的实例 )。通过检查 DummyClass.class 亲自尝试一下。 Ruby 中不存在 C# 意义上的“静态方法”,因为每个方法都是在某个实例上定义(或继承到)并在某个实例上调用的。因此,他们可以访问被调用方可用的任何实例变量。

由于 DummyClass 是一个实例,因此它可以有自己的实例变量。只要您有对类的引用(这应该始终是因为类名是常量),您甚至可以访问这些实例变量。在任何时候,您都可以调用 ::DummyClass.instance_variable_get(:@arr) 并获取该实例变量的当前值。

至于好不好做,要看方法

如果@arr在逻辑上是实例/类DummyClass的“状态”,则将其存储在实例变量中。如果 @arr 仅在 dummy_method2 中用作操作快捷方式,则将其作为参数传递。为了给出使用实例变量方法的示例,请考虑 Rails 中的 ActiveRecord。它允许您执行以下操作:

u = User.new
u.name = "foobar"
u.save

在这里,分配给用户的名称是该用户的合法数据。如果在#save 调用之前询问“此时用户的名字是什么”,您会回答“foobar”。如果您深入研究内部结构(您将深入研究大量元编程,您会发现它们正是为此使用实例变量)。

我使用的示例包含两个单独的公共调用。要查看尽管只进行了一次调用但仍然使用实例变量的情况,请查看 #update_attributes。方法主体很简单 load(attributes, false) &&保存。为什么 #save 没有传递任何参数(例如新的 name),即使它将位于 save 正文中,其中诸如 UPDATE users SET 之类的内容name='foobar' WHERE id=1;?这是因为像名称这样的东西是属于实例的信息。

相反,我们可以看看实例变量没有任何使用意义的情况。查看 #link_to_if 的实现,一种接受布尔型参数的方法(通常是源代码中的表达式)以及通常被 #link_to 接受的参数,例如要链接到的 URL。当布尔条件为真时,它需要将其余参数传递给#link_to并调用它。在这里分配实例变量没有多大意义,因为您不会说这里的调用上下文(渲染器)包含实例中的该信息。渲染器本身没有“要链接到的 URL”,因此不应将其隐藏在实例变量中。

The reason instance variables work on classes in Ruby is that Ruby classes are instances themselves (instances of class Class). Try it for yourself by inspecting DummyClass.class. There are no "static methods" in the C# sense in Ruby because every method is defined on (or inherited into) some instance and invoked on some instance. Accordingly, they can access whatever instance variables happen to be available on the callee.

Since DummyClass is an instance, it can have its own instance variables just fine. You can even access those instance variables so long as you have a reference to the class (which should be always because class names are constants). At any point, you would be able to call ::DummyClass.instance_variable_get(:@arr) and get the current value of that instance variable.

As for whether it's a good thing to do, it depends on the methods.

If @arr is logically the "state" of the instance/class DummyClass, then store it in instance variable. If @arr is only being used in dummy_method2 as an operational shortcut, then pass it as an argument. To give an example where the instance variable approach is used, consider ActiveRecord in Rails. It allows you to do this:

u = User.new
u.name = "foobar"
u.save

Here, the name that has been assigned to the user is data that is legitimately on the user. If, before the #save call, one were to ask "what is the name of the user at this point", you would answer "foobar". If you dig far enough into the internals (you'll dig very far and into a lot of metaprogramming, you'll find that they use instance variables for exactly this).

The example I've used contains two separate public invocations. To see a case where instance variables are still used despite only one call being made, look at the ActiveRecord implementation of #update_attributes. The method body is simply load(attributes, false) && save. Why does #save not get passed any arguments (like the new name) even though it is going to be in the body of save where something like UPDATE users SET name='foobar' WHERE id=1;? It's because stuff like the name is information that belongs on the instance.

Conversely, we can look at a case where instance variables would make no sense to use. Look at the implementation of #link_to_if, a method that accepts a boolean-ish argument (usually an expression in the source code) alongside arguments that are ordinarily accepted by #link_to such as the URL to link to. When the boolean condition is truthy, it needs to pass the rest of the arguments to #link_to and invoke it. It wouldn't make much sense to assign instance variables here because you would not say that the invoking context here (the renderer) contains that information in the instance. The renderer itself does not have a "URL to link to", and consequently, it should not be buried in an instance variable.

小矜持 2025-01-12 19:43:06

这些是类实例变量,在 ruby​​ 中是完全合法的:类也是对象(类的实例),因此也有实例变量。

需要注意的一件事是,每个子类都有自己的一组类实例变量(毕竟这些是不同的对象):如果您对 DummyClass 进行子类化,则子类上的类方法将无法请参阅@arr。

类变量 (@@foo) 当然是相反的:整个类层次结构共享相同的类变量。

Those are class instance variables and are a perfectly legitimate things in ruby: classes are objects too (instances of Class) and so have instance variables.

One thing to look out for is that each subclass will have its own set of class instance variables (after all these are different objects): If you subclassed DummyClass, class methods on the subclass would not be able to see @arr.

Class variables (@@foo) are of course the other way round: the entire class hierarchy shares the same class variables.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文