Ruby:为什么在类方法就足够的情况下实例化一个对象并使用实例方法?

时间:2015-03-03 17:54:03

标签: ruby class design-patterns memory methods

我试图通过阅读其他人编写的代码来学习设计模式。最近我一直关注类方法和实例方法之间的区别。

在我正在阅读的一些代码中,我遇到了以下实例方法的使用:

class Foo
  def bar!(baz)
    # do something to baz
  end
end

my_foo = Foo.new
my_foo.bar!(baz)

为什么在这里使用实例方法? Foo类仅存在bar,所以为什么不使用类方法呢?从我一直在学习的东西,我的倾向就是这样做的:

class Foo
  def self.bar!(baz)
    # do something to baz
  end
end

Foo.bar!(baz)

有没有理由选择第一种模式?这只是一个偏好问题吗?我的想法是,使一个对象使用内存,所以第一个实际上是低效的,但我正在寻找更有经验的人的任何建议。谢谢!

5 个答案:

答案 0 :(得分:3)

没有理由比前者更喜欢前者。由于GC做了更多的工作,实例化一个类可能会导致轻微的性能损失,但我认为你应该问自己这个问题:

  

是否有任何理由创建该类的多个实例?

即。你可以foo = Foo.new然后到处使用foo吗?如果是这样,您根本不需要课程。事实上,类似的论点适用于您的第二个例子。虽然它比第一个改进,但仍然没有理由创建该类的实例。所以不要使用类,使用模块。

module Foo
  def self.bar(baz)
  end
end

答案 1 :(得分:2)

如果您调用的方法是幂等的(即您可以多次调用它而没有副作用并且总是获得相同的结果)并且不依赖于对象的状态(即您不需要初始化class object),使用静态方法绝对没问题。

Foo.bar!(baz)

如果该方法有副作用,或者其结果取决于对象的状态,最好创建一个Foo实例,配置它然后调用你的方法

foo = Foo.new(some_value)
foo.other_value = value_2
foo.bar!(baz)

答案 2 :(得分:2)

你的情况没有太大区别。

使用类创建代码:

  • 更有创意,
  • 通过子类化重用,
  • 在初始化时传递你的参数一次,然后在你的函数中使用其他地方,而不需要为每个函数调用传递相同的参数。

所以任何类方法都可以用实例方法和工作替换,以获得更多抽象。

class Foo
  def initialize baz
    @baz = baz
  end

  def bar!
   # do something to @baz
  end

  def another_function_use_baz
   # do something to @baz
  end
end

my_foo = Foo.new(baz)
my_foo.bar!
my_foo.another_function_use_baz

Check also

答案 3 :(得分:0)

如果方法对其参数做了某些事情,并且没有使用self,例如通过调用另一个实例方法或访问实例变量(直接或间接),那么它确实没有意义成为一个实例方法。

事实上,将作为一个方法是没有意义的。这是一个程序或功能。但是,Ruby实际上没有程序或函数(当然除了Proc个对象之外),所以我们通常做的最接近的事情是private Kernel实例方法(对于puts例如requireMath::abs)或某些单例类的实例方法,例如Math::logmodule Foo def self.bar!(baz) # do something to baz end end 。这在很大程度上取决于该过程是全局有用还是应该是命名空间。

如果这确实是该类唯一的方法,那么通常编写它的方式确实如下:

include

或者可能是这样,这将允许您Foo module Foo module_function def bar!(baz) # do something to baz end end 摆脱命名空间。

def (Foo = BasicObject.new).bar!(baz)
  # do something to baz
end

可能会这样写:

baz

顺便说一句:该方法违反了一个通用的和一个Ruby编码标准:通常,函数,过程,方法等应该修改它们的参数,而你的注释似乎表明方法会修改baz(“做一些 !”)。在Ruby中,应该只有一个以bang(bar!)命名的方法来表示另一个没有爆炸声的方法的更令人惊讶的版本。换句话说,如果还有bar方法,则应该只有{{1}}方法。

答案 4 :(得分:0)

@Marco Sandrini在我看来是对的,但要加上...... 您可以拥有一个具有Pi集的Math类,并且具有使用您自己的参数调用的方法,并且它们不依赖于对象的状态

如果你有一个学生课,如果你打电话给jonny.getAge(),你会需要像DOB这样的某些州,因为它需要jonny的DOB,这与sally的年龄不同。