Ruby include Singleton 和 class << self 有什么区别

tablecell · 2021年09月17日 · 最后由 LiinNs 回复于 2021年09月27日 · 728 次阅读
require "singleton"

class CoderA
  include Singleton

  def self.work
    "crash at 996"
  end
end

class CoderB
  class << self
    def work
      "live at 955"
    end
  end
end

p CoderA.work
p CoderB.work

好象没什么区别

Singleton 是单例的意思,就是只初始化一个类成员instance,并始终使用它。

来自 WIKI 的说明 (链接):

单例模式,也叫单子模式,是一种常用的软件设计模式,属于创建型模式的一种。在应用这个模式时,单例对象的类必须保证只有一个实例存在。许多时候整个系统只需要拥有一个的全局对象,这样有利于我们协调系统整体的行为。比如在某个服务器程序中,该服务器的配置信息存放在一个文件中,这些配置数据由一个单例对象统一读取,然后服务进程中的其他对象再通过这个单例对象获取这些配置信息。这种方式简化了在复杂环境下的配置管理。

你在上面的写法有误,因为实际并没有用到 Singleton,而是在调用类方法

上面的写法等价于:

class CoderA
  def self.work
    "crash at 996"
  end
end

class CoderB
  class << self
    def work
      "live at 955"
    end
  end
end

p CoderA.work
p CoderB.work

class << self 的写法其实只是让包含在此区块中的类方法在定义的时候省略self.

正确的单例写法:

require "singleton"

class CoderA
  include Singleton

  def work
    "crash at 996"
  end
end

p CoderA.instance.work

附文档:https://rubyapi.org/3.0/o/singleton

吓得我,赶紧敲开 irb,复习一遍...

brookepowell 回复

上面的代码是从其他地方抽取后 简化过的,不写 self.work 读不到类变量

require "singleton"

class CoderA
  include Singleton

  attr_accessor :worktime

  def initialize
    @worktime = 996
  end

  def work
    print "work at %d" % self.instance.worktime
  end
end

CoderA.work

gem Singleton 是

The Singleton module implements the Singleton pattern.

是指设计模式里面的 —— 单例模式,即使 new 多次也只有一个实例。

Ruby 自带的 singleton 其实更应该翻译成 元类,他的意思是存在一个 类,这个类看不见 但是用于保存方法。

我之前在这里纠结了一会。实际上 Ruby 可以说是用错词了。还不如叫 meta class

跟楼上一样,对于类,这两个其实是一致的

class CoderA
  def self.work
    "crash at 996"
  end
end

class CoderB
  class << self
    def work
      "live at 955"
    end
  end
end

p CoderA.work
p CoderB.work

tablecell 回复
class CoderA
  include Singleton

  attr_accessor :worktime

  def initialize
    @worktime = 996
  end

  def work
    print "work at %d" % self.worktime
  end
end

CoderA.instance.work
Mark24 回复

class << self 怎么访问 worktime?

楼主混淆了类和实例。

Singleton 用于限制一个类只能生成一个实例,需要使用 #instance 方法获取,得到的是实例。
def self.class << self 设置的是类方法。
attr_accessor 设置的是实例变量。

LiinNs 回复
require "singleton"

class CoderA
  include Singleton

  attr_accessor :worktime

  def initialize
    @worktime = 996
  end

  def self.getWorktime
    @worktime
  end

  def self.setWorktime
    @worktime = 995
    #print self.worktime

  end

  def work
    p  self.worktime === @worktime
    p "self.worktime is %d" % self.worktime
    p "@worktime is  %d" % @worktime
  end

end

CoderA.setWorktime

p CoderA.getWorktime

CoderA.instance.work
p CoderA.getWorktime


实例中的@worktime 和 self 方法中的@worktime 是同一个,还是不同的?

tablecell 回复

不同的

LiinNs 回复

但是长得都一样,怎么区分呢?靠感觉吗?

tablecell 回复

不确定的时候可以利用 Ruby 的 API 协助判断, 比如 #object_id

13 楼 已删除
需要 登录 后方可回复, 如果你还没有账号请 注册新账号