简体   繁体   中英

Ruby: Trouble with scope and class / instance methods

I'm having some trouble understanding scope in ruby.

Here is a link to a repo if you'd like to download/run what I'm talking about to see for yourself:

https://github.com/minervadreaming/killshit

I have several .rb files present - specifically, I'm having an issue calling a class method from an instance. Seems like I'm not properly following scope, but I'm not sure how or why.

Here is a snippet from room.rb:

module KillShit
    class Room
        attr_reader :player, :monster, :game

        def initialize(player, monster, game)
            @player = player
            @monster = monster
            @game = game
        end

        def action
            outline
            Player.describe(player)
            vs
            Monster.describe(monster)
            outline

            #rolling a d20 to see who takes a turn
            turn = rand(1..100)

            if turn <= 20
                monster_attack
            else
                puts "What would you like to do?"
                puts "1. Attack!"
                puts "2. Defend!"
                puts "3. Run away!"
                #Give the player magic if they're at least level 2
                if player.maglevel >= 1
                    puts "4. Cast spell"
                else
                end

                prompt; action = gets.chomp

                if action == "1"
                    attack(player, monster)
                elsif action == "2"
                    defend
                elsif action == "3"
                    flee
                elsif action == "4" && player.maglevel >= 1
                    magic
                else
                    action
                end
            end
        end

        def magic
            puts "What magic would you like to cast?"
            if player.maglevel == 1
                puts "1. Heal"
                puts "2. Fireball"
                puts "3. Tremor"
                prompt; magic = gets.chomp

                if magic == "1"
                    Spells.heal(player)
                elsif magic == "2"
                    Spells.fireball(player, monster)
                elsif magic == "3"
                    Spells.tremor(player, monster)
                else
                    magic
                end
            elsif player.maglevel == 2
                puts "1. Greater Heal"
                puts "2. Firestorm"
                puts "3. Earthquake"
                prompt; magic = gets.chomp

                if magic == "1"
                    Spells.greaterheal(player)
                elsif magic == "2"
                    Spells.firestorm(player, monster)
                elsif magic == "3"
                    Spells.earthquake(player, monster)
                else
                    magic
                end
            else
            end
        end
    end
end

As you can see, when the player chooses to cast a spell it calls out to a Spells class, which I have in spells.rb. Here is a snippet from that code:

require_relative 'room'
require_relative 'player'
require_relative 'monster'

module KillShit
    class Spells
        attr_accessor :player, :monster

    #Checking if user has enough MP to cast spell
        def self.mp_check(req, player)
            req_mp = req
            if player.mp < req_mp
                puts "#{player.name} doesn't have enough MP!"
                action
            else
            end
        end

        def self.heal(player)
            req_mp = 3
            Spells.mp_check(req_mp, player)

            player.mp -= req_mp
            amt = rand(3..10)
            player.hp += amt
            puts "#{player.name} has been healed by #{amt} HP!"
            Room.action
        end
    end
end

The problem is in the "Room.action" call at the end of the self.heal method (or just "action" as was my first attempt, as can be seen in the self.mp_check method). When it is hit, the following error is received:

spells.rb:27:in `heal': undefined method `action' for KillShit::Room:Class (NoMethodError)

I thought that it might've been because I needed to define "action" as a class method with "self." but that isn't doing it. I also thought that it's because I'm trying to call "action" from the Class itself as opposed to the instance of the class with which I am working, and so I should call .action but I can't figure out how to do so.

Any ideas? What should I be reading up on to better understand the concept behind what's happening here? Thanks!

您应该像这样调用Room#action方法:

KillShit::Room.action

Just after a brief look - you did not defined class but instance method action .

Class methods need to by referenced with keyword self or class name directly , so you would need fix the definition this way:

module KillShit
  class Room
    …
    def self.action
        …
    end
    …
  end
end

Updated answer:

module KillShit
  class Room
    def self.action
      puts 'action in Room !'
    end
  end

  class Spells
    def self.heal(player)
      Room.action
    end
  end
end

KillShit::Spells.heal('Wallace')
# action in Room !

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM