普通的实例变量

普通的实例变量,我们没法在 class 外面直接访问

  1. #普通的实例变量,只能在 class 内部访问
  2. class C1
  3. def initialize(name)
  4. @name = name
  5. end
  6. end
  7.  
  8. t1 = C1.new( {'a' => 1, 'b' => 2})
  9. puts t1.name #报错: undefined method `name' for #<Context::C1:0x0000000142cd30 @name={:a=>1, :b=>2}>

如果要想在 class 外访问实例变量,我们可以自己实现实例方法来访问

  1. #普通的实例变量,只能在 class 内部访问
  2. class C1
  3. def initialize(name)
  4. @name = name
  5. end
  6.  
  7. def name
  8. @name
  9. end
  10.  
  11. def name=(arg)
  12. @name=arg
  13. end
  14. end
  15.  
  16. t1 = C1.new( {'a' => 1, 'b' => 2})
  17. puts t1.name() #正确:调用 t1.name 方法
  18. puts t1.name=( {'c' => 3, 'd' => 4} ) #正确:调用 t1.name= 方法
  19. puts t1.name() #正确:{"c"=>3, "d"=>4}

其实这里的 name 和 name= 方法只是故意取名和实例变量有很像,用其它名称也一样

  1. #普通的实例变量,只能在 class 内部访问
  2. class C1
  3. def initialize(name)
  4. @name = name
  5. end
  6.  
  7. def fun1()
  8. @name
  9. end
  10.  
  11. def fun2(arg)
  12. @name = arg
  13. end
  14. end
  15.  
  16. t1 = C1.new( {'a' => 1, 'b' => 2})
  17. puts t1.fun1() #正确:调用 t1.name 方法
  18. puts t1.fun2( {'c' => 3, 'd' => 4} ) #正确:调用 t1.name= 方法
  19. puts t1.fun1() #正确:{"c"=>3, "d"=>4}

attr_reader :arg

attr_reader 限制实例变量 arg 在 class 外部只可读,其相当于在 class 中同时定义了一个 arg 方法

  1. #添加一个可 read 属性,在 class 外部只可 read 该实例变量(等同于通过 instance.arg 方法),而不可对该变量赋值(相当于调用 instance.arg= 方法不存在)
  2. #attr_reader 的限定有点类似 C 中 int const * p的作用,限定的是变量,而非变量指向的对象
  3. class C2
  4. attr_reader :name
  5. def initialize(name)
  6. @name = {'a' => 1, 'b' => 2}
  7. end
  8. end
  9.  
  10. t2 = C2.new( {'a' => 1, 'b' => 2})
  11. puts t2.name # 正确: {"a"=>1, "b"=>2}
  12. puts (t2.name).delete('a') # 正确: attr_reader 保护的是变量 name ,但是变量 name 指向的对象内容是可变的
  13. puts t2.name # 正确: {"b"=>2}
  14. puts t2.name = {'c' => 3} # 报错: undefined method `name=' for #<Context::C2:0x000000021cdf48 @name={"b"=>2}>
  15.  
  16. #为了说明隐式定义了 t2.name() 方法,下面通过方法调用的形式来访问
  17. t2 = C2.new( {'a' => 1, 'b' => 2})
  18. puts t2.name() # 正确: {"a"=>1, "b"=>2}

attr_writer :arg

attr_reader 限制实例变量 arg 在 class 外部只可写,其相当于在 class 中同时定义了一个 arg= 方法

  1. #添加一个可 write 属性,在 class 外部只可 write 该实例变量
  2. class C3
  3. attr_writer :name
  4. def initialize(name)
  5. @name = name
  6. end
  7.  
  8. t3 = C3.new( {'a' => 1, 'b' => 2})
  9. puts t3.name # 报错:undefined method `name' for #<Context::C3:0x0000000140afc8 @name={:a=>1, :b=>2}>
  10. puts t3.name = {'c' => 3} # 正确:{"c"=>3}
  11. 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= 方法

  1. class C4
  2. attr_accessor :name
  3. def initialize(name)
  4. @name = name
  5. end
  6. end
  7.  
  8. t4 = C4.new({'a' => 1, 'b' => 2})
  9. puts t4.name #正确:相当于调用 t4.name() 方法
  10. puts t4.name={'c' => 3, 'd' => 4} #正确:相当于调用 t4.name=() 方法
  11. puts t4.name #正确:{"c"=>3, "d"=>4}
  12. #为了说明隐式定义了 t4.name() 和 t4.name=() 方法,下面通过方法调用的形式来访问
  13. puts t4.name=( {'e' => 5, 'f' => 6} )
  14. puts t4.name() #正确:{"e"=>5, "f"=>6}

ruby 疑难点之—— attr_accessor attr_reader attr_writer的更多相关文章

  1. [No000011]Ruby之attr_reader,attr_writer,attr_accessor理解&用法

    (Ruby/Python/Perl) Ruby 语言与Python和Perl的一个很大区别,在于Ruby中,所有的实例变量都是在类中完全私有的,只能通过accessor 方法来进行变量访问,引用一段代 ...

  2. Ruby attr_reader , attr_writer, attr_accessor方法

    attr_reader方法------读取实例变量 attr_writer方法------改写实例变量 attr_accessor方法-----读写实例变量 class Person attr_rea ...

  3. ruby 疑难点之—— yield 和 yield self

    yield 所有的"方法(methods)"隐式跟上一个"块(block)"参数. 块参数也可以明确给定,形式就是在参数前面加一个"&&quo ...

  4. Ruby类的继承

    Ruby继承的语法 class DerivedClass < BaseClass #some stuff end < 为继承符号 重写(override) 的概念 有时, 我们希望子类从父 ...

  5. Ruby学习-第二章

    第二章 类继承,属性,类变量 1.如何声明一个子类 class Treasure < Thing 这样Thing类中的属性name,description都被Treasure继承 2.以下三种方 ...

  6. ruby简单的基本 3

    类 Ruby一切都是对象,它包含了一个恒定.例如,可以使用.class物业查看对象的类型,你可以看一下1.class.你会发现常1类型是Fixnum,1但它是Fixnum的一个例子. Ruby本类cl ...

  7. Ruby入坑指南

    1.1 简介 Ruby语言是由松本行弘(Matz)设计,是一门通用的.面向对象的.解释型语言. 1.2 Ruby?RUBY?ruby? 1.Ruby:用来表示编程的语言 2.ruby:是指一个计算机程 ...

  8. Ruby语言学习笔记

    在codecademy上开始玩ruby了 1.数据类型:boolean,string,number 变量直接用即可,不用声明(“拿来主义”) 运算符:+ - * / ** % == != && ...

  9. Ruby菜鸟入门指南

    写这篇文章的初衷源于我的伙伴们在上手Ruby过程中,表现实在是太让人拙计了.由于项目的急功近利,需要迅速入门Ruby并上手项目.所以很多开发者在实际开发过程中,不熟悉Ruby的表达方式,也会沿用其他语 ...

随机推荐

  1. hibernate 连接数据库时报错

         错误信息 : com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: No operations allo ...

  2. Caroline--chochukmo

    Caroline--chochukmo 虾米试听 Caroline, Caroline, Caroline, you pulled me into so deep down(内心深处). Caroli ...

  3. Android问题-DelphiXE8安装后编译Android提示SDK无法更新问题(XE10也可以解决)

    资料来原:http://www.chenruixuan.com/archives/479.html (DelphiXE8 更新SDK)http://www.dfwlt.com/forum.php?mo ...

  4. 2015年必火的五个Html5移动开发工具推荐

    NO.1   DCloudHBuilder:基于HTML5开发工具 中文官网:http://www.dcloud.io/ DCloudHBuilder:基于HTML5开发工具是当前最快的HTML开发工 ...

  5. POJ1061青蛙的约会(扩展欧几里得)

    #include <cstdio> #include <cstring> #include <algorithm> #include <math.h> ...

  6. 更新证书错误Code Sign error: Provisioning profile ‘XXXX'can't be found

    在Xcode中当你在更新了你得证书而再重新编译你的程序,真机调试一直会出现 Code Sign error: Provisioning profile ‘XXXX’ can't be found是不是 ...

  7. java中动态代理

    一.在java中怎样实现动态代理 1.我们要有一个接口,还要有一个接口的实现类,而这个实现类呢就是我们要代理的对象 接口: package org.dynamicproxy.test; public ...

  8. Smarty模板中调用PHP函数

    因为应用需要,要在Smarty中调用PHP函数,实现办法如下:模板 数据条数:{$data|count} 活动页面文件后缀:{$page|substr:'-3'} 特殊情况:{$page|str_re ...

  9. DuiVision开发教程(17)-对话框

    DuiVision的对话框类是CDlgBase. 代码中假设须要创建一个对话框,一般建议使用DuiSystem类中封装的若干对话框相关的函数来操作,包括创建对话框.删除对话框.依据对话框名获取对话框指 ...

  10. Html+jquery mobile

    打开VS 2013,选择[文件]-[新建]-[项目] 选择框架为.NET Framework4-[ASP.NET MVC4 Web应用程序],点击[确定] 选择[基本],点击[确定] 创建的MVC的项 ...