Ruby技术问询:如何在不同类之间传递实例变量
嘿,我来帮你理清楚Ruby里不同类之间实例变量传递的正确姿势~首先得明确一个核心点:Ruby的实例变量(比如@zipcode、@full_address)是属于特定对象实例的,默认只能在自身实例内部访问,其他类的实例没法直接读取另一个类实例的@xxx变量——这是面向对象封装特性的要求,你的测试代码[@zipcode, :@full_address]之所以有问题,就是因为直接跨类访问了不属于当前实例的变量。
下面给你几种常用的正确实现方式:
1. 用访问器方法暴露需要的变量
这是最常用也最符合封装原则的方式:给定义实例变量的类添加attr_reader(只读)或attr_accessor(可读可写),生成公开的访问方法,然后持有该类实例的其他类,就可以通过这些方法获取变量值。
举个具体的例子:
# 先给Address类添加访问器 class Address attr_reader :zipcode, :full_address # 自动生成zipcode()和full_address()读取方法 def initialize(zipcode, full_address) @zipcode = zipcode @full_address = full_address end end # Invoice类持有Address实例,通过访问器获取变量 class Invoice def initialize(address) @address = address # 保存Address的实例引用 end def print_shipping_info puts "邮编:#{@address.zipcode}" puts "地址:#{@address.full_address}" end end # 测试使用 my_address = Address.new("90210", "456 Oak Ave, Beverly Hills") my_invoice = Invoice.new(my_address) my_invoice.print_shipping_info # 输出: # 邮编:90210 # 地址:456 Oak Ave, Beverly Hills
如果需要修改Address的变量,可以把attr_reader换成attr_accessor,这样会同时生成读取和修改的方法。
2. 直接传递需要的变量值
如果Invoice只需要Address的某几个变量,不需要持有整个Address实例,那可以在初始化Invoice的时候,直接把需要的变量值传进去:
class Invoice def initialize(zipcode, full_address) @zipcode = zipcode @full_address = full_address end def print_shipping_info puts "邮编:#{@zipcode}" puts "地址:#{@full_address}" end end # 使用时从Address实例获取值传入 my_address = Address.new("90210", "456 Oak Ave, Beverly Hills") my_invoice = Invoice.new(my_address.zipcode, my_address.full_address) my_invoice.print_shipping_info
这种方式适合减少类之间的耦合,当Invoice不需要和Address保持关联时用起来更灵活。
3. 自定义方法返回组合数据
如果需要一次性获取多个相关变量,也可以在Address里写一个自定义方法,返回组合后的结果:
class Address def initialize(zipcode, full_address) @zipcode = zipcode @full_address = full_address end def shipping_details { zipcode: @zipcode, full_address: @full_address } end end class Invoice def initialize(address) @shipping_details = address.shipping_details end def print_shipping_info puts "邮编:#{@shipping_details[:zipcode]}" puts "地址:#{@shipping_details[:full_address]}" end end
这种方式可以把数据封装成更易用的格式,同时保持Address内部变量的私密性。
总结一下:永远不要尝试直接访问其他类实例的@xxx变量,一定要通过公开的方法(访问器或自定义方法)来传递数据,这既符合面向对象的设计原则,也能让你的代码更健壮、更容易维护。
内容的提问来源于stack exchange,提问作者Lucas Barreto

