【问题标题】:Scope of instance variable on class methods类方法上实例变量的范围
【发布时间】:2015-11-15 19:41:45
【问题描述】:

我正在尝试让以下代码工作。

class Animal

end

class Tiger < Animal
    @hunger = 100

    def self.hunger
        @hunger 
    end

    def run
        puts "The Tiger runs"
        @hunger += 10
    end
end

class Statistics
    puts "This tigers hunger is: #{Tiger.hunger}" 
end

tiger = Tiger.new()
tiger.run

所以老虎有一个名为hunger 的变量,它本身位于Tiger 类的顶部。我想这样做,以便可以在整个类方法中更改此变量。例如在run 中,饥饿设置为hunger += 10,但是当我运行此代码时,我得到一个undefined method '+' for nil:NilClass (NoMethodError)。我该怎么做才能使这个程序工作,以便可以更改变量然后在Statistics 类中显示?

【问题讨论】:

    标签: ruby class variables scope


    【解决方案1】:

    问题在于您将类和实例变量/方法完全混合在一起。

    如果你想使用实例(你应该这样做):

    class Animal; end
    
    class Tiger < Animal
      attr_reader :hunger
    
      def initialize
        @hunger = 100
      end
    
      def run
        puts "The Tiger runs"
        @hunger += 10
      end
    end
    
    class Statistics
      def self.show(tiger)
        puts "This tigers hunger is: #{tiger.hunger}" 
      end
    end
    
    tiger = Tiger.new
    tiger.run
    Statistics.show(tiger)
    

    如果你想使用类方法/变量:

    class Animal; end
    
    class Tiger < Animal
      @hunger = 100
    
      def self.hunger
        @hunger
      end
    
      def self.run
        puts "The Tiger runs"
        @hunger += 10
      end
    end
    
    class Statistics
      def self.show
        puts "This tigers hunger is: #{Tiger.hunger}" 
      end
    end
    
    Tiger.run
    Statistics.show
    

    注意@hunger 现在是Tiger 的类实例变量。类实例变量和类变量(用@@ 定义的变量)的区别在于后者由该类的所有后代共享,而前者只与定义它的类相关。

    我不同意你关于Statistic的决定。

    【讨论】:

    • 谢谢!它似乎适用于示例代码,所以我会看看是否可以将它合并到我更大的项目中。
    • 由于 OP 有一个类实例变量(和一个同名的实例变量),而且由于类实例变量通常是比类变量更好的选择,您可能想说一些关于前。
    • @CarySwoveland,说得好。顺便说一下 OP 正在创建他的层次结构,我肯定会让他碰壁。
    • @ndn 感谢您的更新和解释。我将尝试一些答案,看看哪些有效,然后我会选择一个最佳答案。不过我很好奇的一件事。如果我只打算拥有一个 Tiger 实例怎么办?使用@@ 或不使用是否有意义?
    • @JamesMitchell,如果你有一个 Tiger 的实例,你应该定义一个实例而不是使用类变量/方法。但是,如果您的意思是将 Tiger 类视为单个实体 - 只要您不将其子类化并且超类 (Animal) 没有它,@ 987654329@ 会好的。类变量很奇怪。
    【解决方案2】:

    您的 Tiger 类中不需要初始化方法吗?

    def initialize()
    @hunger = 100
    end
    

    我对你的统计课感到困惑。这不应该是 Tiger 类中的一个方法吗?它如何知道 Tiger 访问什么?如果你想这样做,我会添加一个将你的老虎作为参数的方法。

    class Statistics
    def tiger_stat(tiger_name)
    puts "This tigers hunger is: #{tiger_name.hunger}" 
    end
    end
    

    编辑*这是我将使用的代码:

    class Animal
        def initialize(animal_type, hunger_start)
            @animal_type = animal_type
            @hunger = hunger_start
        end
    
        def hunger_print
            puts "This #{@animal_type}'s hunger is: #{@hunger}."
        end
    end
    
    class Tiger < Animal
        def initialize
            super("Tiger", 100)
        end
    
        def run
            puts "The Tiger runs"
            @hunger += 10
        end
    end
    

    这样你可以在任何动物上调用饥饿打印,而不用担心类型或额外的类。你可以做类似的事情。

    tiger = Tiger.new
    tiger.run
    tiger.hunger_print
    

    【讨论】:

    • 我这里的所有代码只是一个更大项目的示例。我有统计类,因为我真的有 3 个动物类,然后统计数据会比较所有动物的饥饿感。我尝试了初始化,但它不起作用。
    • 哦,我明白了。如果您想做类似的事情,我建议您使用继承。你熟悉这个概念吗?
    【解决方案3】:

    您可以使用可从实例和类方法访问的类变量。

    class Animal
      @@hunger = 100
    
      def self.hunger
        @@hunger
      end
    
      def self.increase_hunger
        @@hunger +=1
      end
    
      def hunger
        @@hunger
      end
    
      def increase_hunger
        @@hunger += 1
      end
    end
    
    Animal.increase_hunger
    puts Animal.hunger # => 101
    animal = Animal.new
    animal.increase_hunger
    puts animal.hunger # => 102
    

    【讨论】:

      猜你喜欢
      • 2014-03-12
      • 1970-01-01
      • 1970-01-01
      • 2011-08-22
      • 2023-03-19
      • 2011-08-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多