简体   繁体   中英

Accessing a Class' instance variable from outside

I understand (I think) the difference between class variables and instance variables of a class in Ruby.

I'm wondering how one can access the instance variables of a class from OUTSIDE that class.

From within (that is, in a class method instead of an instance method), it can be accessed directly, but from outside, is there a way to do MyClass.class.[@$#]variablename ?

I don't have any specific reason for doing this, just learning Ruby and wondering if it is possible.

class MyClass

    @my_class_instance_var = "foo"

    class << self
        attr_accessor :my_class_instance_var
    end

end

puts MyClass::my_class_instance_var

The foregoing yields:

>> foo

I believe that Arkku demonstrated how to access class variables (@@), not class instance variables (@) from outside the class.

I drew the foregoing from this essay: Seeing Metaclasses Clearly

Ruby has Class, Class Object, and Instance.

A Class variable belongs to a Class.
A Class instance variable belongs to a Class Object

Class variable:

Accessible within the class and its instances.
attr_accessor does not work on class variables.

Class instance variable:

Accessible only through the Class.
attr_accessor works if you define it in the class and not in the class object as below.

class A
    @b = 1
    class << self
        attr_accessor :b
    end
end

Defining a getter and setter on the instances for the class instance variable b in:

class A
    @b = 1
    class << self
        attr_accessor :b
    end
    def b
        A.b
    end
    def b=(value)
        A.b=value
    end
end

Now the class instance variable b can be accessed via the owner Class and its instances.
As a several days old ruby learner, this is the most I can do.

`irb(main):021:0* class A
irb(main):022:1> @b = 1
irb(main):023:1> class << self
irb(main):024:2> attr_accessor :b
irb(main):025:2> end
irb(main):026:1> def b
irb(main):027:2> A.b
irb(main):028:2> end
irb(main):029:1> def b=(v)
irb(main):030:2> A.b=v
irb(main):031:2> end
irb(main):032:1> end
=> :b=
irb(main):033:0> A.b
=> 1
irb(main):034:0> c = A.new
=> #<A:0x00000003054440>
irb(main):035:0> c.b
=> 1
irb(main):036:0> c.b= 50
=> 50
irb(main):037:0> A.b
=> 50
irb(main):038:0>`

Yes, I'm begining to dislike ruby...iso a better solution.

In ruby you can achieve this in 2 ways

  1. manually defining getter and setters
  2. using attr_* methods

Let me elaborate the above ways for you,

Manually defining getter and setters

class Human
  def sex=(gender)
    @sex = gender
  end

  def sex
    @sex
  end
end

//from outside  class 
human = Human.new
// getter method call 
puts human.sex
// setter method call to explicitly set the instance variable 
human.sex = 'female'

puts human.sex 
// now this prints female which is set

using attr_* methods

class Human
  attr_accessor :sex
end

//from outside 

human = Human.new
// getter method call 
puts human.sex
// setter method call to explicitly set the instance variable 
human.sex = 'female'

puts human.sex 
// now this prints female which is set 

attr_accessor internally creates setter and getter methods for you, if you want only setter you can just use attr_writer and if you want only getter you can use attr_reader.

I hope, I answered your question

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