首页 > 解决方案 > 类方法中的变量

问题描述

你能解释一下为什么attribute_accessors不能访问类变量吗?

当我在这里尝试在一个数组中列出所有子类的所有方法时,它的工作方式略有不同。它在每个子类中创建了数组@method_names,每个类都有特定的方法......所以我确实需要通过子类进行循环。

@method_names 是什么类型的变量/属性?

谢谢!

module First
      class First_class
        class << self
          def info
            puts "First_class method info."
            puts @subclasses
            puts @method_names
          end
      
          def inherited(subclass)
            puts "#{subclass} located ..."
            subclasses << subclass
          end
    
          def subclasses
            @subclasses ||= []
          end
    
          def method_added(method_name)
            puts "Method located #{method_name} ..."
            method_names << method_name
          end
    
          def method_names
            @method_names ||= []
          end
        end
     
        def initialize
          puts "Instance of First_class is created."
        end
    
        def first_method
        end
      end
    
      class Second_class < First_class
        def self.info
          puts "Second_class method info."
          puts @subclasses
          puts @method_names
        end
        
        def second_method
        end
    
        def initialize
          puts "Instance of Second_class is created."
        end
      end
    
      class Third_class < First_class
        def third_method
        end
    
        def initialize
          puts "Instance of Third_class is created."
        end
      end
    end

    
    First::First_class.subclasses.each {
        |subclass| puts subclass
      subclass.method_names.each {
        |methodn| puts methodn
      }
    }

################UPDATE######### 好吧,也许我把问题放错了。

基本上,如果我不创建对象实例,@@method_names(类变量)和@method_names(实例变量)有什么区别?在将更多输入插入@method_names 后,它仍会插入相同的object_id。那么@@method_names 有什么好处呢?

标签: ruby

解决方案


更新以回答更新的问题。

ruby 中的类可以有类变量。但是,如果您修改类级别变量,所有实例都将被修改。不建议这样做,但会说明这一点。但也看到这个答案

class Foo
  @@bar = 'bar'

  attr_accessor :bar

  def initialize
    @bar = 'bar'
  end

  def class_bar
    @@bar
  end

  def change_class_bar string
    raise ArgumentError unless string.is_a?(String)
    @@bar = string
  end
end

a = Foo.new
b = Foo.new

# change the class variable @@bar
b.change_class_bar 'wtf?'

# see both instances are changed because objects are passed by referrence
print 'a.class_bar is: '
puts a.class_bar
print 'b.class_bar is: '
puts b.class_bar

# change one instance only
a.bar = 'only a has changed'
print 'a.bar is: '
puts a.bar
print 'b.bar is still: '
puts b.bar

运行这个,你应该得到输出:

a.class_bar is: wtf?
b.class_bar is: wtf?
a.bar is: only a has changed
b.bar is still: bar

原来的答案留在这里

@method_names是实例化它的类的实例的实例变量。但是,除非这些属性是使用定义的 getter 或 setter 方法定义的,否则无法访问它以进行读/写。

ff = First::First_class.new
Instance of First_class is created.
=> #<First::First_class:0x00007fde5a6867b8>
ff.method_names
NoMethodError: undefined method `method_names' for #<First::First_class:0x00007fde5a6867b8>
Did you mean?  methods

现在,如果您调用ff.methods,您将看到通过标准 Ruby 继承定义的所有方法。

作为旁注,Ruby 中的类名通常使用PascalCase参见PascalCaseMixed_case气馁。


推荐阅读