Project1
标题: 新手问attr_reader 问题 [打印本页]
作者: kvkv97 时间: 2014-10-17 11:12
标题: 新手问attr_reader 问题 实变量属于个体对象的变量称为实变量。局部变量只有在 def ~ end 等结构内部使用时才有效,然而使用实变量的话,只要其对象存在,变量的值就会被保存。实变量一般作为对象的属性来使用。
1,“只要其对象存在,变量的值就会被保存”是怎么理解的?
class Person
def name
return @name
end
def name=(name)
@name = name
end
def hello
print "我是" + @name
end
end
alex = Person.new
alex.name = "艾力克斯"
alex.hello # => 我是艾力克斯
上面的示例是先准备 @name 实变量,使用 name、name= 方法把对象附加上 @name 实变量作为属性。
2,“使用 name、name= 方法把对象附加上 @name 实变量作为属性”是怎么理解的?
3,参数name可以改成a吗?name和name=的name是相同概念吗?
attr_accessor :name
这样编写是,自动定义与 : 符号右侧名称相同的实变量对应属性的取得和注解方法。上例中是生成 @name 实变量并附加成为属性。
4,“自动定义与 : 符号右侧名称相同的实变量对应属性的取得和注解方法”可以简化成“定义与 : 符号右侧名称相同的实变量对应属性的取得和注解的Ruby方法”吗?
在只定义属性的取得方法的情况下,一般使用 attr_reader 代替 attr_accessor。
5, attr_reader 和 attr_accessor的含义有什么不同?
作者: H·H·Y 时间: 2014-10-17 13:27
本帖最后由 H·H·Y 于 2014-10-17 13:32 编辑
attr_accessor :name
同等于
def name
return @name
end
def name=(name)
@name = name
end
于是在定义实例之后直接使用.name方法便可以读取到@name实例变量,同时输入.name=×可以将数值×赋值到@name,就是说attr_accessor :name允许了name的读取和写入。
attr_reader :name则设name为只读:
def name
return @name
end
同等的,attr_writer则为只需要写入。
def name=(name)
@name = name
end
同为脚本新人,如有错误各位大触请多多调教
作者: RyanBern 时间: 2014-10-17 13:59
1.由于实变量是属于某个对象的,因此,只要对象存在,那么属于它的实变量就会一直存在。这个没什么好说的。就比如一个人是“人类”的对象,那么这个人的“大脑”(可以看作它的一个实变量)就会存在(暂且不说能不能访问到)。那么,既然已经有你这个人了,而大脑本身是属于人类对象的一个变量,那它岂有不存在之理?
2.这个要说一下变量的存在性和访问性。你要清楚变量存在性和访问性完全是两回事。就像你知道有中南海这个地方,但是你却没有机会“访问”它一样。(咳咳,和谐)上面已经说明,对象存在,那么属于它的实变量就会存在。但是这些实变量能否被访问到呢?这就不好说了。“访问”的意思你现在可以理解为读取和修改。有些实变量需要和外界访问,有些则不需要,所以我们要采用定义方法的方式对实变量进行访问。因为,普通方法是可以访问实例变量的。
于是,定义name和name=也就不难理解了。定义name的意思就是取出对象的实变量@name,而定义name=的意思就是对@name变量进行修改。
3.形式参数可以随便改。name=和name实际是两个方法名字,所以其实'name'的含义只是方便人的理解,对于机器来说是一样的。而且这两个方法名字和@name这个变量没有什么必然联系。
class Person
def initialize
@name = ""
end
def ryanbern
return @name
end
def ryanbern=( a)
@name = a
end
end
class Person
def initialize
@name = ""
end
def ryanbern
return @name
end
def ryanbern=( a)
@name = a
end
end
如此定义,对于一个Person类的对象alex,调用alex.ryanbern就可以得到它的@name,调用alex.ryanbern = "RyanBern"就可以修改它的@name。
不过,很少有人这么做,除非他想作死,既然方法的作用是读取或修改对应的实变量,那么为什么要定义个完全不一样的标识符来给自己找麻烦?所以,一般人还是会定义成name和name=这两个方法的。
因此,attr_Xxxx :系列便诞生了。例如,写下attr_accessor :name,就等同于做了三件事情:为对象准备@name实变量;定义朴素的name方法;定义朴素的name=方法。这样写能更方便编写程序吧。请注意写下的是“朴素的name方法”和“朴素的name=方法”,也就是说用attr_accessor :name这种方式定义的变量,只具备最简单的读取和修改功能,你调用.name方法,它就把@name拿出来给你看,你调用.name=方法,它就会把@name改成你的参数,非常天真。
class Person
def initialize
@name = "Ryan"
end
def name
return @name .upcase
end
def name=( name)
@name += name
end
end
alex = Person.new
p alex.name #=>"RYAN"
alex.name = "Bern"
p alex.name #=>"RYANBERN"
class Person
def initialize
@name = "Ryan"
end
def name
return @name .upcase
end
def name=( name)
@name += name
end
end
alex = Person.new
p alex.name #=>"RYAN"
alex.name = "Bern"
p alex.name #=>"RYANBERN"
仔细体会上面的例子,attr_accessor :遇到这样的情况就无能为力了。
4.不明白这样简化意义在什么地方。
5.attr_reader :name只做了两件事:为对象准备@name实变量;定义朴素的name方法。和attr_accessor :name相比少了一个。通常,如果你不希望从外部来修改实变量的值,就可以定义attr_reader :或者你要定义不那么朴素的'name='和朴素的'name'方法,也可以这样做。同理,attr_writer :name也只做了两件事,为对象准备@name实变量;定义朴素的name=方法。
class A
attr_writer :x
def initialize
@x = 0
end
end
a = A.new
a.x += 1
class A
attr_writer :x
def initialize
@x = 0
end
end
a = A.new
a.x += 1
↑以上的例子有错误(如果看不出就跑一下,会报错),请说明原因。
作者: RyanBern 时间: 2014-10-17 18:01
继续回答。
我们拿“黑猫”来举例,说说属性和对象的关系。
class Cat
attr_accessor :color
def initialize
[ url=home.php ?mod=space&uid=10453 ] @color[ /url] = "Black"
end
end
class Cat
attr_accessor :color
def initialize
[ url=home.php ?mod=space&uid=10453 ] @color[ /url] = "Black"
end
end
猫类有一个属性叫做“颜色color”,这个属性的值是“黑Black”。color方法和color=方法,它们执行的过程依赖于实变量@color。
我们说属性依赖于对象存在而存在,意思是和属性有关的那个实变量是存在于对象中的。实际上,对象无非就是一些实变量构成的,这些实变量中,有的单独可以用来描述“对象的特性”,我们可以认为这样的实变量有特殊的地位,因此就利用attr_accessor :使之升华为“属性”。
那么,属性本质上是方法还是变量?严格来说,属性是方法。这点从属性的机制就能看出。由于attr_accessor :和def name, def name=(name)效果相同,所以属性实际上和方法无异。因此,属于属性的标识符是name,name=这样的东西。
所以可以这样去理解:属性是依赖于一些实例变量的特殊方法。由于属性本身的可以表示有特殊的(实际)含义的实变量,因此极易把属性和实变量混为一谈。
欢迎光临 Project1 (https://rpg.blue/)
Powered by Discuz! X3.1