Project1

标题: attr_reader和attr_accessor的区别 [打印本页]

作者: 七仙女    时间: 2009-3-10 06:28
提示: 作者被禁止或删除 内容自动屏蔽
作者: 小小大恶魔    时间: 2009-3-10 06:32
提示: 作者被禁止或删除 内容自动屏蔽
作者: 七仙女    时间: 2009-3-10 06:59
提示: 作者被禁止或删除 内容自动屏蔽
作者: 八云紫    时间: 2009-3-10 07:01
class A
  def name=(val)
    @name = val
  end
end

a = A.new;

a.name = 3;  # 这句相当于是 a.name=(3)
[LINE]1,#dddddd[/LINE]系统信息:本贴获得楼主认可,66RPG感谢您的热情解答~ [LINE]1,#dddddd[/LINE]版主对此帖的认可:『感谢详细的回答』,积分『+200』。
作者: 七仙女    时间: 2009-3-10 07:05
提示: 作者被禁止或删除 内容自动屏蔽
作者: 八云紫    时间: 2009-3-10 07:08
@name 不可读取~~~
作者: 七仙女    时间: 2009-3-10 15:00
提示: 作者被禁止或删除 内容自动屏蔽
作者: redant    时间: 2009-3-10 18:16
我也有问题还不大懂 = =

class A
  
def name=(r)
    @name = r
  $g=@name

end
end


p $g    # nil 是因为确实没有
a = A.new;
a.name = 3
p $g    # 3 name被赋值为3
p @name #nil 是因为@name 不能被读取 但其实已经改变?
class A
def name(r)
  @name = r
  $g=@name
end
end
p $g    # 3 name赋值为3 没有变
a = A.new;
a.name(8)
p $g    # 8 被重新赋值为8
exit

还有就是def name=(r)
= 为什么要紧挨着name ?
作者: Quarcy    时间: 2009-3-10 18:36
作用域啊作用域啊!
$ 的作用域是「全系統」
@ 的作用域是「該實例內部」
def name=(r) 与 def name(r) 有什么区别  

我可以說祗是名字不同嗎……
實際上 「=」 也是方法名字的一部分啊 [LINE]1,#dddddd[/LINE]版主对此帖的认可:『感谢详细的回答』,积分『+200』。
作者: TERENCE    时间: 2009-3-10 18:48
@变数名  
该类变数里面的东西 生存时间仅仅只有在类里面,
这类的变数能在某一个calss下在不同的方法(def 方法名)間下运作,内容不会消失
而不是不能读取
class A
def name=(val)
  @name = val
end
end
a = A.new
a.name = 3
p @name # 在class外 所以显示出来为nil
def name=(val)
  @name = val
  p @name
end
end
a = A.new
a.name = 3
# 在class內 所以每次调用都会显示出来 而不是nill


$变数名
又名全域变数
该类变数里面的东西 生存时间很长
跨类跨方法里面的内容都不会消失
作者: 七仙女    时间: 2009-3-10 19:23
提示: 作者被禁止或删除 内容自动屏蔽
作者: TERENCE    时间: 2009-3-10 19:31
其实没有区别
一个名字叫def name=(r)
另一个叫def name(r)
如此而已

同样都是给该方法一个值代入
只是在调用方法的时候 写出来de 樣式不一样

def name=(val)
@name = val
end
end
a = A.new
a.name = 3

def name(val)
@name = val
end
end
a = A.new
a.name(3)
[LINE]1,#dddddd[/LINE]系统信息:本贴获得楼主认可,66RPG感谢您的热情解答~
作者: 八云紫    时间: 2009-3-10 20:18
以下引用redant于2009-3-10 10:16:20的发言:

我也有问题还不大懂 = =

class A

def name=(r)
   @name = r
$g=@name

end
end


p $g    # nil 是因为确实没有
a = A.new;
a.name = 3
p $g    # 3 name被赋值为3
p @name #nil 是因为@name 不能被读取 但其实已经改变?
class A
def name(r)
@name = r
$g=@name
end
end
p $g    # 3 name赋值为3 没有变
a = A.new;
a.name(8)
p $g    # 8 被重新赋值为8
exit

还有就是def name=(r)
= 为什么要紧挨着name ?


name=  类似与重载了 = 运算符, 只是类似
作者: Quarcy    时间: 2009-3-10 20:28
以下引用八云蓝于2009-3-10 12:18:02的发言:

Ruby裏面應該沒有「重載」這個概念……某次想用重載功能來寫一點東西,結果死活找不到相關說明。在某個討論當中甚至看到有人說:「像是Ruby這樣的弱類型語言不需要重載功能……」

而事實上也的確如此。因此,我更認為把「name=」當作一個整體方法名字來處理比較好,就像「include?」一樣。不過祗是允許調用的時候把「=」隔離變成這樣「.name = 」……算是特例吧--
作者: 八云紫    时间: 2009-3-10 20:32
以下引用Quarcy于2009-3-10 12:28:37的发言:

Ruby裏面應該沒有「重載」這個概念……某次想用重載功能來寫一點東西,結果死活找不到相關說明。在某個討論當中甚至看到有人說:「像是Ruby這樣的弱類型語言不需要重載功能……」

而事實上也的確如此。因此,我更認為把「name=」當作一個整體方法名字來處理比較好,就像「include?」一樣。不過祗是允許調用的時候把「=」隔離變成這樣「.name = 」……算是特例吧--


所以吾只是说类似。
作者: TERENCE    时间: 2009-3-10 23:58
(2009-3-10 11:41:25)     [redant]
就是 = 紧挨着的话 就是方法的一部分
单个 = 就是赋值

是这样么?

就赋值的本意来说...
赋值是给予一个数值代入的意思
def name(r) 与 def name=(r)
都有赋予数值计算的作用

写成def name(r)这样
是表答像数学上的sin(x)或f(x)的函式型式

而写成def name=(r)这样
是表达类似於一个变数的型式

要选择哪种写法 那要看你的脚本怎么写

如果你的方法单纯只是回传某值 建议使用前者

如果你调用的方法要做繁复的计算 或 在方法内最后利用
"@变数"存东西以便以后计算 又或者自运算  建议使用后者

-------------------------
以上是某龙仔的看法....写法思路仅参考用
顺道回应redant给我的短信疑问
[LINE]1,#dddddd[/LINE]版主对此帖的认可:『感谢详细的回答』,积分『+200』。
作者: 八云紫    时间: 2009-3-11 00:50
说的具体点那吧。

RGSS 里的类内部的变量,除了 全局变量(以 $ 开头) 外, 类里的变量都是对外不可见的,

就是说在没有这顶写入或者读取方法的时候, 类变量不能在类以外使用,比如:

  1. class A
  2.   def initialize(number)
  3.     @numner = numner;
  4.   end
  5. end

  6. a = A.new(3);
  7. p a.number #=> nil number对外不可读取
  8. a.number = 4  #=> 错误, @number 在类定义的外部不可改变。
复制代码


这样做的原因是为了保护类的数据,达到 面向对象 的一个指标, 封装
在有的时候必须要在外部使用类里的类变量,这里就要使用 接口方法。

类里的方法是可以访问到类变量的,所以就需要定义一个方法,让方法来改变变量的值,

而不是让我们直接修改,可以把上面的脚本稍作修改:

  1. class A
  2.   def initialize(number)
  3.     @numner = numner;
  4.   end
  5.   def read_number
  6.     return @number;
  7.   end
  8.   def write_number(new_number)
  9.     @number = new_number;
  10.   end
  11. end

  12. a = A.new(3);
  13. p a.read_number #=> 现在可以读取 number 的值了
  14. a.write_number(4)  #=> 通过方法来 间接 的修改类变量的值。
复制代码


   这样的话,某个类变量的值就可以对外可见了。 汝也可以只定义 read_number 或者是

write_number(new_number),已达到限制类外部访问变量的权利。

   说的给明白点,其实修改类变量的不是我们,而是类里的方法。

   当然,如果都使用以上的定义的话,方法名称想起来感觉很麻烦,所以,就换一个写法:

  1. class A
  2.   def initialize(number)
  3.     @numner = numner;
  4.   end
  5.   def number
  6.     return @number;
  7.   end
  8.   def number=(new_number)
  9.     @number = new_number;
  10.   end
  11. end

  12. a = A.new(3);
  13. p a.number #=> 现在可以读取 number 的值了
  14. a.number=(4)  #=> 通过方法来 间接 的修改类变量的值,或者是 a.number = 4
复制代码


    这样方法的意思与作用就清晰了。

    注意这句 a.number ,这里的 number 不是类变量,而是方法的名字,方法返回

的不是 @number 而是 @number 的值。

    a.number=(4) 和 a.number = 4 写法不一样,但是意思与效果都是一样的。

    RGSS 里为我们定义了一个操作,使得写法更清晰,所以,在修改一下脚本:

  1. class A
  2.   attr_accessor :numner
  3.   def initialize(number)
  4.     @numner = numner;
  5.   end
  6. end

  7. a = A.new(3);
  8. p a.number #=> 现在可以读取 number 的值了
  9. a.number = 4  #=> 通过方法来 间接 的修改类变量的值。
复制代码


   是不是清晰很多,代码也少了好多。

   总结一下,
   
   attr_accessor :numner 相当于是:

  def number
    return @number;
  end
  def number=(new_number)
    @number = new_number;
  end

   而 attr_reader   :number 相当于是:

  def number
    return @number;
  end

   attr_writer   :number 相当于是:

  def number=(new_number)
    @number = new_number;
  end [LINE]1,#dddddd[/LINE]版主对此帖的认可:『超赞超详细 {/qiang}』,积分『+100』。




欢迎光临 Project1 (https://rpg.blue/) Powered by Discuz! X3.1