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