我试图通过阅读其他人编写的代码来学习设计模式。最近我一直关注类方法和实例方法之间的区别。
在我正在阅读的一些代码中,我遇到了以下实例方法的使用:
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)
有没有理由选择第一种模式?这只是一个偏好问题吗?我的想法是,使一个对象使用内存,所以第一个实际上是低效的,但我正在寻找更有经验的人的任何建议。谢谢!
答案 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
答案 3 :(得分:0)
如果方法仅对其参数做了某些事情,并且没有使用self
,例如通过调用另一个实例方法或访问实例变量(直接或间接),那么它确实没有意义成为一个实例方法。
事实上,将作为一个方法是没有意义的。这是一个程序或功能。但是,Ruby实际上没有程序或函数(当然除了Proc
个对象之外),所以我们通常做的最接近的事情是private
Kernel
实例方法(对于puts
例如require
或Math::abs
)或某些单例类的实例方法,例如Math::log
或module 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的年龄不同。