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

Ruby中ProcessTrip类的total_amount_collected为何被判定为私有方法?

问题:未声明private的实例方法为何被视为私有方法?

报错信息

调用total_amount_collected方法时触发如下错误:

trip.total_amount_collected
NoMethodError: private method `total_amount_collected' called for #<ProcessTrip:0x0000000110e33da0>
from (pry):3:in `get_total_collection'

调用代码

def get_total_collection
  trip =  ProcessTrip.new
  trip.total_amount_collected
  sort_passengers(total_collection); 
  print_summary(total_collection) if @print_summary
end  

相关类代码

ProcessTrip类(含错误写法)

class ProcessTrip < MetroCardClassMethods
attr_accessor :travel_history, :station, :destination 

def initialize  
   
end    
def update_balace_aumount(balance_details,trip_to,trip_complete)
      effective_tarif = trip_complete ? passenger_tarif_for(_passenger_type) / 2 : passenger_tarif_for(_passenger_type)
      trip_to['discount']= effective_tarif if trip_complete
      trip_to['discount']= 0 if !trip_complete
     if   balance_details["balance"].to_i < effective_tarif
      effective_trip_cost = effective_tarif  - balance_details["balance"].to_i
      trip_to["trip_cost"] +=  effective_trip_cost*0.02
      balance_details["balance"] = 0;
     else
      balance_details["balance"] =  balance_details["balance"].to_i - effective_tarif
     end      
    end 
end

def total_amount_collected ()
  @@vertex.each do |metro_id, travel_history| 
    result = find_amount_collected_for_metrocard(self.class.card_list[metro_id], travel_history)     
    result.each do |key,value| 
      self.class.collection[key]["cost"]+=value["trip_cost"];
      self.class.collection[key]["discount"]+=value["discount"];   
      self.class.collection[key]["passengers"]+=value["passenger"];     
    end
   
  end
  return @@collection
end

def find_amount_collected_for_metrocard(balance_details, trip_info)    
  trip_from={}
  trip_info.each do |station, destination| 
    @station = station             
    if _is_return_journey(trip_from)    
      process_trip_segment(trip_from,_destination,_station)   
      trip_from[_station]["trip_cost"] = passenger_tarif_for(_passenger_type) * 0.5    
      update_balace_aumount(balance_details, trip_from[_station], true); 
    else               
      process_trip_segment(trip_from,_station,_station)       
      trip_from[_station]["trip_cost"] = (trip_from[_station]["trip_cost"] || 0) + passenger_tarif_for(_passenger_type)          
      update_balace_aumount(balance_details, trip_from[_station], false);  
    end           
  end    

return  trip_from

end 

MetroCardClassMethods父类

class MetroCardClassMethods
  @@card_list = []
  @@vertex = {};
  @@collection={"CENTRAL"=>{"cost"=>0,"discount"=>0,"passengers"=>[]},"AIRPORT"=>{"cost"=>0,"discount"=>0,"passengers"=>[]}}
  @@station_from = {"CENTRAL"=>"AIRPORT","AIRPORT"=>"CENTRAL"}
  @@station = []

  def initialize(item)
    @travel_history =  {}  
    @metro_id = item["metro_id"] 
    @station = item["station"]
    @passenger_type = item["passenger_type"] 
    @destination = @@station_from[@station] 
  end

  class << self   
   
    def card_list=(card_list)
      @@card_list=card_list
    end 
    def card_list
      @@card_list
    end  
    def collection
      @@collection
    end  

    def station_from
      @@station_from
    end  
    def vertex
      @@vertex
    end  
  end  
 
end

原因解析

核心问题是代码结构错误:

  • total_amount_collected和find_amount_collected_for_metrocard被定义在了ProcessTrip类的外部(类的end语句之后),这会导致这两个方法被自动添加到Object类中。
  • Ruby顶级作用域中,直接定义的方法默认是Object类的私有实例方法——因为顶级作用域的self是main(属于Object的实例),这类方法会被默认设为私有。
  • 当用ProcessTrip实例调用total_amount_collected时,Ruby会沿继承链查找:ProcessTrip→MetroCardClassMethods→Object,最终找到Object中的私有方法,因此触发私有方法调用错误。
  • 而update_balace_aumount是在ProcessTrip类内部定义的,属于ProcessTrip的公开实例方法,所以可以正常调用。

修复方案

将total_amount_collected和find_amount_collected_for_metrocard移动到ProcessTrip类的end之前,确保它们属于ProcessTrip类的实例方法:

class ProcessTrip < MetroCardClassMethods
attr_accessor :travel_history, :station, :destination 

def initialize  
   
end    
def update_balace_aumount(balance_details,trip_to,trip_complete)
      effective_tarif = trip_complete ? passenger_tarif_for(_passenger_type) / 2 : passenger_tarif_for(_passenger_type)
      trip_to['discount']= effective_tarif if trip_complete
      trip_to['discount']= 0 if !trip_complete
     if   balance_details["balance"].to_i < effective_tarif
      effective_trip_cost = effective_tarif  - balance_details["balance"].to_i
      trip_to["trip_cost"] +=  effective_trip_cost*0.02
      balance_details["balance"] = 0;
     else
      balance_details["balance"] =  balance_details["balance"].to_i - effective_tarif
     end      
end    

def total_amount_collected ()
  @@vertex.each do |metro_id, travel_history| 
    result = find_amount_collected_for_metrocard(self.class.card_list[metro_id], travel_history)     
    result.each do |key,value| 
      self.class.collection[key]["cost"]+=value["trip_cost"];
      self.class.collection[key]["discount"]+=value["discount"];   
      self.class.collection[key]["passengers"]+=value["passenger"];     
    end
   
  end
  return @@collection
end

def find_amount_collected_for_metrocard(balance_details, trip_info)    
  trip_from={}
  trip_info.each do |station, destination| 
    @station = station             
    if _is_return_journey(trip_from)    
      process_trip_segment(trip_from,_destination,_station)   
      trip_from[_station]["trip_cost"] = passenger_tarif_for(_passenger_type) * 0.5    
      update_balace_aumount(balance_details, trip_from[_station], true); 
    else               
      process_trip_segment(trip_from,_station,_station)       
      trip_from[_station]["trip_cost"] = (trip_from[_station]["trip_cost"] || 0) + passenger_tarif_for(_passenger_type)          
      update_balace_aumount(balance_details, trip_from[_station], false);  
    end           
  end    

return  trip_from

end 
end # 该end属于ProcessTrip类

内容的提问来源于stack exchange,提问作者Moin Ahmed

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 23:54:59