ruby 疑難點之—— attr_accessor attr_reader attr_writer


普通的實例變量

普通的實例變量,我們沒法在 class 外面直接訪問

#普通的實例變量,只能在 class 內部訪問
class C1
    def initialize(name)
        @name = name
    end
end

t1 = C1.new( {'a' => 1, 'b' => 2})
puts t1.name                             #報錯: undefined method `name' for #<Context::C1:0x0000000142cd30 @name={:a=>1, :b=>2}>

如果要想在 class 外訪問實例變量,我們可以自己實現實例方法來訪問

#普通的實例變量,只能在 class 內部訪問
class C1
    def initialize(name)
        @name = name
    end
    
    def name
        @name
    end
    
    def name=(arg)
        @name=arg
    end
end

t1 = C1.new( {'a' => 1, 'b' => 2})
puts t1.name()                               #正確:調用 t1.name 方法
puts t1.name=( {'c' => 3, 'd' => 4} )        #正確:調用 t1.name= 方法
puts t1.name()                               #正確:{"c"=>3, "d"=>4}

其實這里的 name 和 name= 方法只是故意取名和實例變量有很像,用其它名稱也一樣

#普通的實例變量,只能在 class 內部訪問
class C1
    def initialize(name)
        @name = name
    end
    
    def fun1()
        @name
    end
    
    def fun2(arg)
        @name = arg
    end
end

t1 = C1.new( {'a' => 1, 'b' => 2})
puts t1.fun1()                               #正確:調用 t1.name 方法
puts t1.fun2( {'c' => 3, 'd' => 4} )         #正確:調用 t1.name= 方法
puts t1.fun1()                               #正確:{"c"=>3, "d"=>4}

 

attr_reader :arg

attr_reader 限制實例變量 arg 在 class 外部只可讀,其相當於在 class 中同時定義了一個 arg 方法

#添加一個可 read 屬性,在 class 外部只可 read 該實例變量(等同於通過 instance.arg 方法),而不可對該變量賦值(相當於調用 instance.arg= 方法不存在)
#attr_reader 的限定有點類似 C 中 int const * p的作用,限定的是變量,而非變量指向的對象
class C2
    attr_reader :name
    def initialize(name)
        @name =  {'a' => 1, 'b' => 2}
    end
end

t2 = C2.new( {'a' => 1, 'b' => 2})
puts t2.name                                      # 正確: {"a"=>1, "b"=>2}
puts (t2.name).delete('a')                        # 正確: attr_reader 保護的是變量 name ,但是變量 name 指向的對象內容是可變的
puts t2.name                                      # 正確: {"b"=>2}
puts t2.name = {'c' => 3}                         # 報錯: undefined method `name=' for #<Context::C2:0x000000021cdf48 @name={"b"=>2}>

#為了說明隱式定義了 t2.name() 方法,下面通過方法調用的形式來訪問
t2 = C2.new( {'a' => 1, 'b' => 2})
puts t2.name()                                    # 正確: {"a"=>1, "b"=>2}

 

attr_writer :arg

attr_reader 限制實例變量 arg 在 class 外部只可寫,其相當於在 class 中同時定義了一個 arg= 方法

#添加一個可 write 屬性,在 class 外部只可 write 該實例變量
class C3
    attr_writer :name
    def initialize(name)
        @name = name
    end

t3 = C3.new( {'a' => 1, 'b' => 2})
puts t3.name                           # 報錯:undefined method `name' for #<Context::C3:0x0000000140afc8 @name={:a=>1, :b=>2}>
puts t3.name = {'c' => 3}              # 正確:{"c"=>3}
puts (t3.name).delete(:c)              # 報錯:(沒有定義方法 name,所以不能用這種方式企圖獲取到 name 變量指向的對象): undefined method `name' for #<Context::C3:0x000000021e9c70 @name={"c"=>3}>

 

attr_accessor :arg

attr_reader 限制實例變量 arg 在 class 外部只可讀,其相當於在 class 中同時定義了一個 arg 和 arg= 方法

class C4
    attr_accessor :name
    def initialize(name)
        @name = name
    end
end

t4 = C4.new({'a' => 1, 'b' => 2})
puts t4.name                                        #正確:相當於調用 t4.name() 方法
puts t4.name={'c' => 3, 'd' => 4}                   #正確:相當於調用 t4.name=() 方法
puts t4.name                                        #正確:{"c"=>3, "d"=>4}
#為了說明隱式定義了 t4.name() 和 t4.name=() 方法,下面通過方法調用的形式來訪問
puts t4.name=( {'e' => 5, 'f' => 6} ) 
puts t4.name()                                      #正確:{"e"=>5, "f"=>6}   

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM