之间有什么区别
module Logging
def self.log
if @logger.nil?
@logger = Logger.new STDOUT
end
@logger
end
end
这个?
class Logging
def self.log
if @logger.nil?
@logger = Logger.new STDOUT
end
@logger
end
end
他们似乎都做同样的事情。为什么我会选择一个而不是另一个?
答案 0 :(得分:4)
tl; dr :Ruby中没有类方法和模块方法,只有实例方法。考虑到它们都只是实例方法,因此也是同样的事情,不可能有任何区别。
Ruby中没有“类方法”或“模块方法”。 Ruby只有一种方法:实例方法。
在讨论使用实例方法的某种模式时,我们有时会使用 word “类方法”或“模块方法”,但是没有这样的Ruby中的概念。 “类方法”和“模块方法”实际上只是对象的单例方法,恰好是Module
类或Class
类的实例。对象的单例方法(恰好是Class
,Module
,String
,Array
,Hash
的实例之间绝对没有区别, Object
,Foo
,Bar
,Whatever
或Garbledigookidoo
。
喔。我提到了吗? Singleton方法也不存在。同样,它是我们用于某些方法用法的单词,但它们实际上只是对象的单例类的常规无聊的旧实例方法。
但是,“foo
的单例类的实例方法”和“{1}}的单例类的实例方法,其中Foo
是Foo
的实例”真的很长,所以我们将它们缩短为“Class
的单一方法”和“foo
的类方法”,方便了解完全正确那些是实际上并不存在于该语言中。
与Java有三种不同的方法(实例方法,静态方法和构造函数(有点像方法)),Ruby只有一种方法:实例方法。没有类方法,没有模块方法,没有全局方法,没有顶级方法,没有静态方法,没有构造函数。然而, 有三种类:常规类,单例类和包含类(后者是在调用Foo
时被合成并注入到继承层次结构中的类或者include
)。这些类的不同之处主要在于prepend
,Object#class
和Class#superclass
等方法是显示还是抑制它们。 Singleton类被所有类都抑制,包括前两个类,但由Class#ancestors
显示。
答案 1 :(得分:2)
JörgMittag是正确的,技术上没有类方法或模块方法。但是,我将假设“类方法”表示“在类实例的单例类上定义的实例方法”,而“模块方法”则表示“在Module实例的单例类上定义的实例方法”。 / p>
两者之间没有功能差异。两者都在命名空间中定义方法。
在实践中,您会发现它们往往用于不同的目的。例如,类方法通常指定构造对象的不同方式,例如, Puzzle.from_textfile
。模块方法只是放在单个命名空间中的全局函数,因为它们在逻辑上是相关的,例如, Math.sin
和Math.abs
。
同样重要的是要注意Ruby也有“模块功能”的概念,这与这个问题无关。术语“模块功能”是指模块上的类方法,该模块具有相同的私有实例方法。这些可以使用Module.module_function
以编程方式创建,并且在将模块用作命名空间和mixin(例如Math
)时非常有用。
答案 2 :(得分:1)
模块是关于提供可以在多个类中使用的方法 - 将它们视为“库”(正如您在Rails应用程序中看到的那样)。类是关于对象的;模块是关于功能的
请参阅this
答案 3 :(得分:0)
模块与类类似,它们包含方法,常量和其他模块和类定义的集合。与类不同,您无法基于模块创建对象。
模块有两个目的。首先,它们充当命名空间,允许您定义名称不会与其他位置定义的方法冲突的方法。其次,它们允许您在类之间共享功能 - 如果类混合在一个模块中,该模块的实例方法变得可用,就好像它们已在类中定义一样。多个类可以混合在同一个模块中,在不使用继承的情况下共享模块的功能。您还可以将多个模块混合到一个类中。
类是为了创建对象。
答案 4 :(得分:0)
您想了解Ruby中的类和实例方法之间的差异。
看到不同的行为很重要。忽略下面的类语法并关注功能,尤其是调用两种方法类型的方式。
下面是一个包含两个方法的类,第一个是类方法,第二个是实例方法。
class Invoice
# Class method
def self.print_out
"Printed out Invoice"
end
# Instance method
def convert_to_pdf
"Converted to PDF"
end
end
如果您注意到,语法的唯一区别在于我使用世界 self ,用于类方法,并使用名称本身作为实例方法。
现在,当我想调用类方法时,我能够通过(。)声明类的名称,然后是方法名,如下所示:
class Invoice
# Class method
def self.print_out
"Printed out Invoice"
end
# Instance method
def convert_to_pdf
"Converted to PDF"
end
end
Invoice.print_out
继续将此代码复制并粘贴到Repl.it中,您将看到结果。
如果我尝试使用相同的语法调用实例方法,则会抛出错误:
class Invoice
# Class method
def self.print_out
"Printed out Invoice"
end
# Instance method
def convert_to_pdf
"Converted to PDF"
end
end
Invoice.convert_to_pdf
再次,将其复制并粘贴到Repl.it,您将看到错误,应该说 convert_to_pdf 是一种未定义的方法。要运行实例方法,我们需要创建该类的实例来运行它。
您需要像这样实例化一个新的发票:
i = Invoice.new
i.convert_to_pdf
在Repl.it中运行此方法时,它会打印消息而不会出现错误。试试吧。
现在,如果我尝试以与调用实例方法相同的方式访问我的类方法,则会导致错误。
因此,可以结合类的名称调用类方法,而实例方法要求您创建一个实例来调用该方法。
现在,话虽如此,我实际上可以将我的代码快捷一点,以便在与类名相同的行上调用我的实例方法:
Invoice.new.convert_to_pdf
这将正常工作。但是,通常以这种方式调用方法是没有意义的,因为您无法对其进行太多操作。因此,访问实例方法的早期方法更好。
那么,为什么在调用类方法时更容易使用实例方法呢?
让我们想象你班上有15种方法,你不想在你的课程中多次打电话给班级。我不会在这里提供一个例子,因为写一些没用的东西会太难看和耗费时间。
每次打电话给班级都不好看,被认为是糟糕的编程习惯。从本质上讲,这是在程序中创建15个新对象。
创建实例变量并使用它调用所有方法是一种更好的做法。
这样您每次都不会创建该类的新实例,而是为所有方法使用相同的实例。
这些是Ruby中可用的不同类型的方法以及如何调用它们。