You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何创建相同属性值时复用同一object_id的Ruby类

Ruby同值对象复用类实现方案

问题核心

目标是实现与Symbol一致的实例复用逻辑(享元模式):相同入参调用构造方法返回同一实例(object_id一致)。Ruby默认的Class#new方法每次调用都会分配新内存生成独立对象,无法直接满足该要求;另外初始代码存在构造方法名错误,Ruby构造方法固定为initialize,写为init不会在调用new时自动执行属性赋值。

正确实现代码

class PixKey
  # 类层面缓存已创建的实例,key为传入的pix密钥值,value为对应实例
  @instances = {}

  class << self
    # 重写默认构造入口,实现复用逻辑
    def new(key)
      # 命中缓存直接返回已有实例,未命中则创建新实例存入缓存
      @instances[key] ||= super(key).freeze
    end

    # 可选方法:用于清空实例缓存,适配测试或特殊业务场景
    def clear_cache
      @instances.clear
    end
  end

  attr_reader :key

  # 屏蔽外部直接调用原始new方法,避免绕过缓存生成重复实例
  private_class_method :new

  def initialize(key)
    # 存储key的冻结副本,避免外部传入的字符串被修改影响实例状态
    @key = key.dup.freeze
  end

  # 补全相等判断逻辑,即使未来逻辑调整也能保证同key实例相等
  def ==(other)
    other.is_a?(PixKey) && other.key == @key
  end
  alias eql? ==

  # 重写hash方法,保证实例作为Hash键时行为符合预期
  def hash
    [self.class, @key].hash
  end
end

实现说明

  • 第一次传入某key调用PixKey.new时,会检查缓存,无对应实例则调用原始new方法创建实例,冻结后存入缓存再返回
  • 后续传入相同key调用构造方法时,直接返回缓存中已存在的实例,object_id完全一致,和Symbol的复用行为完全匹配
  • 冻结实例和内部key值,是为了防止运行时修改实例属性破坏缓存映射关系
  • 重写==、eql?、hash方法后,实例可以安全作为Hash键、Set元素使用,行为和值对象一致

测试验证

原RSpec测试用例可直接通过,相同key两次调用new返回的是同一对象,不会再出现object_id不一致的报错。


内容的提问来源于stack exchange,提问作者Davi Luis

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 05:21:24