为什么某些类和/或方法可以在没有父类实例的情况下被调用?

bro*_*web 5 ruby class

我即将完成 Code Academy 的 Ruby 课程,我对一件奇怪的事情感到好奇:我的印象是类是常量、方法等的存储库......并且为了访问大多数情况下,您首先需要创建该类的实例,或者在某些情况下可以调用它们自己的方法(因为它们在技术上都是全局对象的一部分)。然后我看到了这样的事情:

#Worked
Time.now
Run Code Online (Sandbox Code Playgroud)

我将其理解为调用类 [Time] 实例的方法 [now]。然后我尝试单独调用该方法:

#Failed
now
Run Code Online (Sandbox Code Playgroud)

那失败了,我假设虽然可以在一般范围内创建一个方法[作为全局对象的一部分],但如果它依赖于“父”类的初始化变量,则不能单独调用它,因为它会不知道要在哪个对象中搜索那些已初始化的变量。接下来我创建了一个测试类:

class Clock
  def initialize
    @hours = 1
    @minutes = 30
  end

  def showTime
    puts "The time is: #{@hours}:#{@minutes}"
  end
end

#this worked
watch = Clock.new
watch.showTime

#this failed
showTime
Run Code Online (Sandbox Code Playgroud)

然后我创建了一个基本方法(假设它在全局级别)

def mymethod
    puts "The mighty METHOD!"
end

#Works
mymethod
Run Code Online (Sandbox Code Playgroud)

并按照我的方式调用此方法,而不引用全局对象。所以...我的问题如下:

  1. 如何以这种方式调用 [Time.now]?不应该首先创建一个 Time 实例吗?
  2. 为什么我不能[now] 单独调用该方法?我说得对吗,它依赖于以这种方式调用时找不到的资源?
  3. 为什么我不能单独调用 showTime 方法?但是如果我在“全局”级别定义任何方法,我可以在不引用全局对象的情况下访问它

aku*_*uhn 5

首先,你的直觉是正确的。

\n\n

每个方法都必须是某个接收者的实例方法。

\n\n

全局方法被定义为Object类上的私有实例方法,因此似乎是全局可用的。为什么?从任何上下文Object总是在类层次结构中self,因此私有方法Object总是可以在没有接收者的情况下调用。

\n\n
def fuuuuuuuuuuun\nend\n\nObject.private_methods.include?(:fuuuuuuuuuuun)\n# => true\n
Run Code Online (Sandbox Code Playgroud)\n\n

类方法被定义为其类实例的“单例类”上的实例方法。Ruby 中的每个对象都有两个类,一个“单例类”,其实例方法仅适用于该单个对象;另一个“普通类”,其方法适用于该类的所有对象。类没有什么不同,它们是Class类的对象,并且可能具有单例方法。

\n\n
class A\n  class << self # the singleton class\n    def example\n    end\n  end\nend\n\nA.singleton_class.instance_methods.include?(:example)\n# => true\n
Run Code Online (Sandbox Code Playgroud)\n\n

定义类方法的替代方法是

\n\n
class A\n  def self.example\n  end\nend\n\n# or \n\ndef A.example\nend\n
Run Code Online (Sandbox Code Playgroud)\n\n

有趣的是,您可以使用相同的语法在任何对象(不仅仅是类对象)上定义单例方法,def (receiver).(method name)如下所示

\n\n
str = "hello"\n\ndef str.square_size\n  size * size\nend\n\nstr.square_size\n# => 25\n\n"any other string".square_size\n# => raises NoMethodError\n
Run Code Online (Sandbox Code Playgroud)\n\n
\n\n

一些编程语言历史 \xe2\x80\x94 Singleton 类取自 Smalltalk 语言,在那里它们被称为“元类”。基本上,Ruby 中的所有面向对象功能(以及 上的函数式枚举器Enumerable)都取自 Smalltalk 语言。Smalltalk 是一种早期的基于类的面向对象语言,创建于 70 年代。它也是发明图形用户界面(例如重叠窗口和菜单等)的语言。如果你喜欢 Ruby,也许也看看 Smalltalk,你可能会再次爱上它。

\n