Ruby:为什么第二段代码,类似于第一段代码 - 给出'undefined method'错误?



我不明白,"dungeon.rb"如何运行正常,而"tarifs.rb"

则粉碎:

undefined 方法 'full_description' for nil:NilClass(NoMethodError).

这两段代码是相似的。 有什么不同:类的名称,一些方法名称及其参数。

### OK piece -> dungeon.rb code
class Dungeon             
    attr_accessor :player 
    def initialize(player)
        @player = player  
        @rooms  = {}      
    end
    def add_room(reference, name, description, connections)
        @rooms[reference] = Room.new(reference, name, description, connections)
    end
    def start(location)            
        @player.location = location
        show_current_description    
    end
    def show_current_description
        puts "Location: " + find_room_in_dungeon(@player.location).full_description
    end
    def find_room_in_dungeon(reference)
        @rooms[reference]
    end
    def find_room_in_direction(direction)
        find_room_in_dungeon(@player.location).connections[direction]
    end  
    def go(direction)
        puts "nYou go: " + direction.to_s
        @player.location = find_room_in_direction(direction)
        show_current_description
        puts "Where you want to go now? "
    end
end
class Player
    attr_accessor :name, :location
    def initialize(name)
        @name = name
    end
end
class Room
    attr_accessor :reference, :name, :description, :connections
    def initialize(reference, name, description, connections)
        @reference   = reference
        @name        = name
        @description = description
        @connections = connections
    end
    def full_description
        @name + "nn ** You are in " + @description
    end
end
#######---------------- Creating Player and Dungeon objects ------------------
puts         "Enter your name"
username   = gets.chomp
player     = Player.new(username)
my_dungeon = Dungeon.new(player)
#######---------------- Add rooms to the dungeon ----------------------
my_dungeon.add_room(:largecave,
        "Large Cave",
        "a large cavernous cave **",
        {:west  => :smallcave,
         :south => :grotto,
         :east  => :largecave })
my_dungeon.add_room(:smallcave,
    "Small Cave",
        "a small, claustrophobic cave **",
        {:west  => :smallcave, 
         :south => :grotto,
         :east  => :largecave })
my_dungeon.add_room(:grotto,
        "Wet Grotto",
        "a medium range grotto with water pool in center **",
        {:west  => :smallcave, 
         :south => :grotto,
         :east  => :largecave })
puts "Your name is: #{player.name}"
#######------------ Start the dungeon by placing the player in the large cave ------------------------
my_dungeon.start(:largecave)
#######------------- Player navigation ---------------------
ok_input = [:west, :east, :south, :exit]
loop do
    puts "Choose direction please: "
    input = gets.chomp.to_sym
    if ok_input.include?(input)
        my_dungeon.go(input)
    elsif ok_input.include?(input) == false
        puts "Wrong input!!! Allowed input: 'west', 'east', 'south' or 'exit' "
    end
    break if input == :exit
end

#### NOT OK piece -> tarifs.rb code
class Invest
   attr_accessor :user
       def initialize(user)
       @user   = user
       @tarifs = {}
   end
   def add_tarif(reference, tname, description, connections, procent, days)
       @tarifs[reference] = Tarif.new(reference, tname, description, connections, procent, days)
end
   def start(choosed_tarif)
       @user.choosed_tarif = choosed_tarif
       show_current_description
end
   def show_current_description
       puts "  Current tarif is: " +   find_tarif_in_tarifs(@user.choosed_tarif).full_description
   end
   def find_tarif_in_tarifs(reference)
       @tarifs[reference]
   end
   def find_tarif_in_direction(direction)
       find_tarif_in_tarifs(@user.choosed_tarif).connections[direction]
   end
   def go(direction)
       puts "nYou choosed: " + direction.to_s
       @user.choosed_tarif = find_tarif_in_direction(direction)
       show_current_description
   end
end
class User
   attr_accessor :uname, :choosed_tarif        
   def initialize(uname)
       @uname = uname
   end
end
class Tarif
   attr_accessor :reference, :tname, :description, :connections, :procent, :days
   def initialize(reference, tname, description, connections, procent, days)
       @reference   = reference
       @tname       = tname
       @description = description
       @connections = connections
       @procent     = procent
       @days        = days
   end
   def full_description
      @tname + "n  " + @description
   end
end
#######-------- Creating User and Invest objects ----------
puts        "Enter your name"
uname    =  gets.chomp
user     =  User.new(uname)
my_tarif =  Invest.new(user)
#######-------- Adding tariffs to the Invest --------------
my_tarif.add_tarif(:start,
                   "Start",
                   "Start tarif 2% daily for 3 days in total",
                   {:first  => :start,
                   :second => :business,
                   :third  => :profi },
                   2,
                   3)
my_tarif.add_tarif(:business,
                   "Business",
                   "Business tarif 3% daily for 5 days in total",
                   {:first  => :start,
                    :second => :business,
                    :third  => :profi },
                    3,
                    5)
my_tarif.add_tarif(:profi,
                   "Profi",
                   "Profi tarif 4% daily for 10 days in total",
                   {:first  => :start,
                    :second => :business,
                    :third  => :profi },
                    4,
                    10)
#######-------- Autostarts with first tarif --------------
my_tarif.start(:business)
#######-------- Tarif navigation --------------
ok_input = [:start, :business, :profi, :exit] 
puts "Choose your tarif: "
input    = gets.chomp.to_sym
if       input == :start
         my_tarif.go(input)
   elsif input == :business
         my_tarif.go(input)
   elsif input == :profi
         my_tarif.go(input)
   else  puts "Please input 'start', 'business' or 'profi' !!!"
end

tarifs.rb 代码必须允许在 tarifs.rb 中导航 - 就像 dungeon.rb 代码允许在房间中导航一样。同时,tarifs.rb 输出显示:

tarifs.rb:22:in show_current_description': undefined methodfull_description' for nil:NilClass (NoMethodError) from tarifs.rb:36:in go' from tarifs.rb:111:in'

您正在nil上呼叫 mehtod full_description.问题在于这些方法:

   def show_current_description
       puts "  Current tarif is: " +   find_tarif_in_tarifs(@user.choosed_tarif).full_description
   end
   def find_tarif_in_tarifs(reference)
       @tarifs[reference]
   end

您根据find_tarif_in_tarifs(@user.choosed_tarif)的结果调用full_description,即在@tarifs[@user.choosed_tarif]上。显然,没有在哈希@tarifs为该用户注册关税。

您必须处理这种情况 - 通过检查返回值是否不是 nil, 定义show_current_description if find_tarif_in_tarifs(@user.choosed_tarif) 将"当前 tarif 是:"find_tarif_in_tarifs(@user.choosed_tarif).full_description 还 把"未找到关税" 结束

或通过从find_tarif_in_tarifs返回默认值

   def show_current_description
     @tarifs.fetch(references, default_tariff) #(you need to define default_tariff method)
   end

相关内容

  • 没有找到相关文章

最新更新