顶级的类变量访问

时间:2015-09-27 03:53:52

标签: ruby-on-rails ruby

我是Ruby的初学者。我正在学习目前正在学习Ruby的艰辛之路的第45课,我正在创建一个类似于Zork和Adventure的游戏。

我创建了一个结构,我在不同的文件中创建'场景'并要求所有场景都在一个文件中,我有一个引擎/地图,确保当前场景不等于'完成'它运行'X '场景''输入'方法。

但是我有两个问题: 1)我一直收到错误提示“警告类变量从顶层访问” 2)即使脚本正在运行,我也得到了

ex45.rb:30:in `play': undefined method `enter' for nil:NilClass (NoMethodError) from ex45.rb:59:in

以下是我每个文件的所有代码。我很抱歉,如果这是一个很长的阅读,但我很想知道为什么我得到这两个错误以及我可以做些什么来解决它们。

Ex45.rb:

require "./scene_one.rb"
require "./scene_two.rb"
require "./scene_three.rb"

@@action = SceneOne.new
@@action_two = SceneTwo.new
@@action_three = SceneThree.new

class Engine

    def initialize(scene_map)
        @scene_map = scene_map
    end

    def play()      
        current_scene = @scene_map.opening_scene()
        last_scene = @scene_map.next_scene('finished')

        while current_scene != last_scene
            next_scene_name = current_scene.enter()
            current_scene = @scene_map.next_scene(next_scene_name)
        end

        current_scene.enter()
    end
end


class Map

    @@scenes = {
        'scene_one' => @@action,
        'scene_two' => @@action_two,
        'scene_three' => @@action_three
    }

    def initialize(start_scene)
        @start_scene = start_scene
    end

    def next_scene(scene_name)
        val = @@scenes[scene_name]
        return val
    end

    def opening_scene()
        return next_scene(@start_scene)
    end
end

a_map = Map.new('scene_one')
a_game = Engine.new(a_map)
a_game.play()

scene_one.rb:

类SceneOne

  def enter
    puts "What is 1 + 2?"
    print "> "

    answer = $stdin.gets.chomp

    if answer == "3"
        puts "Good job"
        return 'scene_two'
    else
        puts "try again"
        test
    end
  end

end

scene_two.rb

class SceneTwo

    def enter
        puts "1 + 3?"
        print "> "

        action = $stdin.gets.chomp

        if action == "4"
            return 'scene_three'
        else
            puts "CANNOT COMPUTE"
        end
    end

end

scene_three.rb

class SceneThree

    def enter
        puts "This is scene three"
    end

end

提前致谢!

2 个答案:

答案 0 :(得分:3)

回答您的第一个问题

您需要在Map类中移动类变量定义以消除这些警告:

Ex45.rb:5: warning: class variable access from toplevel
Ex45.rb:6: warning: class variable access from toplevel
Ex45.rb:7: warning: class variable access from toplevel

所以,你的Map类看起来像这样:

class Map
    @@action = SceneOne.new
    @@action_two = SceneTwo.new
    @@action_three = SceneThree.new

    @@scenes = {
        'scene_one' => @@action,
        'scene_two' => @@action_two,
        'scene_three' => @@action_three
    }

    def initialize(start_scene)
        @start_scene = start_scene
    end

    def next_scene(scene_name)
        val = @@scenes[scene_name]
        return val
    end

    def opening_scene()
        return next_scene(@start_scene)
    end
end

回答第二个问题:

您收到undefined method 'enter' for nil:NilClass (NoMethodError),因为您的current_scene在某个时候变为nil,然后您尝试致电:current_scene.enter()nil.enter,但它失败了错误信息。

要解决此问题,您必须确保current_scene中始终有一些价值,即确保它不是nil

我认为,您可以从current_scene.enter()课程中的play方法的末尾删除Engine行。因此,您的Engine课程将如下所示:

class Engine
    def initialize(scene_map)
        @scene_map = scene_map
    end

    def play()      
        current_scene = @scene_map.opening_scene()
        last_scene = @scene_map.next_scene('finished')

        while current_scene != last_scene
            next_scene_name = current_scene.enter()
            current_scene = @scene_map.next_scene(next_scene_name)
        end

        # current_scene.enter()
    end
end

而且,你不会再犯这个错误了。

答案 1 :(得分:0)

你知道吗:

@@y = 20
p Object.class_variables

--output:--
1.rb:1: warning: class variable access from toplevel
[:@@y]

class Object
  def self.y
    @@y
  end
end

puts Object.y

--output:--
20

可是:

class Dog
  @@y = "hello"

  def self.y
    @@y
  end
end

puts Dog.y     #=>hello
puts Object.y  #=>What do you think?

最后一行的输出是ruby中不使用类变量的原因。您应该使用所谓的 类实例变量 ,而不是类变量

class Object
  @y = 10   #class instance variable

  def self.y
    @y
  end
end

puts Object.y


class Dog
  @y = "hello"

  def self.y
    @y
  end
end

puts Dog.y     #=> hello
puts Object.y  #=> 10

一个类实例变量只是一个@variable,它位于类中,但在任何def之外。而不是所有子类共享一个 @@ variable ,而每个子类都有自己的 @variable