Account=Struct.new(:first_name,:last_name)classUserattr_reader:accountdefinitialize(account)@account=accountenddeffirst_nameaccount.first_nameenddeflast_nameaccount.last_nameenddeffull_name"#{first_name}#{last_name}"endenduser=User.new(Account.new('foo','bar'))putsuser.first_nameputsuser.last_nameputsuser.full_name#=>foo#=>bar#=>foo bar
require'forwardable'Account=Struct.new(:first_name,:last_name)classUserattr_reader:accountextendForwardabledef_delegators:account,:first_name,:last_name#若 User 不想對外開放,attr_reader :account,可以改成實例變數,如以下#extend Forwardable#def_delegators :@account, :first_name, :last_namedefinitialize(account)@account=accountenddeffull_name"#{first_name}#{last_name}"endenduser=User.new(Account.new('foo','bar'))putsuser.first_nameputsuser.last_nameputsuser.full_name#=>foo#=>bar#=>foo bar
require'forwardable'classBicycleattr_reader:size,:partsdefinitialize(args={})@size=args[:size]@parts=args[:parts]enddefsparesparts.sparesendendclassPartsextendForwardable#@parts 是一個 Array,因此將 size 和 each 委派給 Parts 實例物件def_delegators:@parts,:size,:each#為了要讓實例可以直接用 select,select 又會用到 each 所以上面要委派includeEnumerabledefinitialize(parts)@parts=partsenddefspares#所以這裡才可以直接用 select,不用 @parts.selectselect{|part|part.needs_spare}endendclassPartattr_reader:name,:description,:needs_sparedefinitialize(args)@name=args[:name]@description=args[:description]@needs_spare=args.fetch(:needs_spare,true)endendchain=Part.new(name:'chain',dsescription:'10-speed')tire_size=Part.new(name:'tire_size',description:'23')tap_color=Part.new(name:'tap_color',description:'red')road_bike=Bicycle.new(size:'L',parts:Parts.new([chain,tire_size,tap_color]))putsroad_bike.parts.sizeputs'*'*10putsroad_bike.spares.sizeputs'*'*10