Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby:既然一个类方法就足够了,为什么要实例化一个对象并使用实例方法呢?_Ruby_Class_Design Patterns_Memory_Methods - Fatal编程技术网

Ruby:既然一个类方法就足够了,为什么要实例化一个对象并使用实例方法呢?

Ruby:既然一个类方法就足够了,为什么要实例化一个对象并使用实例方法呢?,ruby,class,design-patterns,memory,methods,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方法呢?据我所知,我倾向于这样做: class Foo def self.b

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

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

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

my_foo = Foo.new
my_foo.bar!(baz)
为什么在这里使用实例方法?
Foo
类的存在只是为了做
bar
,所以为什么不使用class方法呢?据我所知,我倾向于这样做:

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

Foo.bar!(baz)

有什么理由支持第一种模式吗?这只是偏好的问题吗?我的想法是,制作一个对象需要内存,因此第一个对象实际上效率很低,但我希望从更有经验的人那里得到任何建议。谢谢

没有理由选择前者而不是后者。由于GC做了更多的工作,实例化一个类可能会对性能造成轻微的影响,但我认为您真的应该问自己这个问题:

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

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

module Foo
  def self.bar(baz)
  end
end
如果该方法仅对其参数执行某些操作,而不使用
self
,例如通过调用另一个实例方法或访问实例变量(直接或间接),那么它作为实例方法确实没有意义

事实上,它作为一种方法是毫无意义的。这是一个过程或一个函数。然而,Ruby并没有真正的过程或函数(当然除了
Proc
对象),所以我们通常做的最接近的事情是
内核
私有
实例方法(例如
put
require
)或某个单例类的实例方法,例如
Math::abs
Math::log
。这在很大程度上取决于该过程是全局有用还是应该使用名称空间

如果这真的是该类拥有的唯一方法,那么编写该类的通常方法应该是:

module Foo
  def self.bar!(baz)
    # do something to baz
  end
end
或者像这样,这将额外允许您
包含
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

顺便说一句:该方法违反了一个通用和一个Ruby编码标准:一般来说,函数、过程、方法等不应该修改它们的参数,而您的评论似乎表明该方法确实修改了
baz
(“做点什么
baz
)。在Ruby中,应该只有一个名为bang(
)的方法来表示另一个名为unbang的方法的更令人惊讶的版本。换句话说,应该只有一个
bar
方法,则使用code>方法。

如果调用的方法是幂等的(即,可以多次调用它而不会产生副作用,并且始终获得相同的结果),并且不依赖于对象的状态(即,不需要初始化类对象),则使用静态方法是绝对正确的

Foo.bar!(baz)
如果方法有副作用,或者其结果取决于对象的状态,那么最好创建一个Foo实例,配置它,然后调用您的方法

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

你的情况没有多大差别

使用类生成代码:

  • 更具创意,
  • 可通过子类化重复使用
  • 初始化时只传递一次参数,然后在函数中的其他位置使用它,而无需向每个函数调用传递相同的参数
因此,任何类方法都可以用实例方法和工作来代替,以获得更多的抽象



@Marco Sandrini在我看来是对的,但更重要的是。。。 你可以有一个数学类,它有Pi集,有你用自己的参数调用的方法,它们不依赖于对象的状态


然而,如果你有一个学生班,如果你调用jonny.getAge()的话,你会需要像DOB这样的特定状态,因为它需要jonny的DOB,这与sally的年龄不同

这篇来自CODECIMLATE的博客对防止重构的类方法提出了一个相当坚实的观点,如果该方法可能特别复杂的话,这可能需要考虑:类方法也使得引入意外全局变量更容易,这通常被认为是差的设计。最后,正如链接文章中提到的,实例化一个对象所需的内存对代码的性能可能可以忽略不计(但如果有许多实例化,那么它值得进行基准测试)。如果不需要实例化某些对象,则模块将获胜!
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