使用Ruby的属性

查看任何面向对象的代码,它或多或少都遵循相同的模式。创建一个对象,调用该对象上的一些方法并访问该对象的属性。在那里'除了将它作为参数传递给另一个对象's方法之外,您可以对一个对象做些什么。但是我们在这里关心的是属性。

属性就像可以通过对象点符号访问的实例变量。例如,人物姓名 会访问一个人的名字。同样,您可以经常分配给类似的属性人物姓名="Alice"。这与成员变量(如C++)类似,但不完全相同。在这里没有什么特别之处,使用"getters"and"setters,"或从实例变量中检索和设置属性的方法,以大多数语言实现属性。

Ruby没有't区分属性getter和setter以及正常方法。由于Ruby'灵活的方法调用语法,不需要区分。例如,人物姓名人物姓名()是同一件事,你'用零参数重新调用name方法。一个看起来像一个方法调用,另一个看起来像一个属性,但它们'实际上都是同一件事。他们'都只是调用name方法。类似地,任何以等号(=)结尾的方法名称都可以用于分配。声明人物姓名=&##34;Alice"完全相同人物姓名=(alice),即使属性名称和等号之间有空格,它仍然只是调用name=方法。

01

of 03

自己实现属性

关闭woman'在家使用笔记本电脑的手

您可以自己轻松实现属性。通过定义集合ter和getter方法,您可以实现任何您希望的属性。这里'是一些实现person类的name属性的示例代码。它将名称存储在@name实例变量中,但名称不't必须相同。请记住,这些方法没有什么特别之处。

#!防控新型冠状病毒肺炎健康知识/usr/bin/env ruby class Person def initialization(name)@name=name end def name@name end def name=(name)@name=name end def say_Helloplaces"hello,#{@name}&##34;end end

你要注意的一件事是,这是很多工作。它'很多输入只是说你想要一个名为name的属性访问@name实例变量。幸运的是,Ruby提供了一些方便的方法来为您定义这些方法。

02

77 of 03 78

使用attrÅreader,attrÅwriter和attrÅaccessor

模块类中有三种方法可以在类声明中使用。请记住,Ruby不区分运行时和"编译时间,"类声明中的任何代码不仅可以定义方法,还可以调用方法。调用attrë读者,attrëwriter和attrëaccessor方法将反过来定义我们在上一节中定义的setter和getter。

attrÅ阅读器方法的效果就像它的听起来一样。它采用任意数量的符号参数,并且对于每个参数,定义一个返回相同名称的实例变量的"getter"方法。因此,我们可以用前一个示例中的name方法替换为attrÅreader:name

类似地,attrëwriter方法为传递给它的每个符号定义一个"setter"方法。请注意,等号不一定是符号的一部分,而只是属性名称。我们可以代表将前一个示例中的name=方法放置为attrÅwritier:name

正如预期的那样,attrÅaccessor完成attrÅwriterattrÅreader的工作。如果您同时需要setter和getter来获取属性,通常的做法是不要分别调用这两种方法,而是调用attrëu accessor。我们可以将前一个示例中的名称名称=方法替换为attrÅaccessor:name

#!/usr/bin/env ruby def person attr#accessor:name def initiate(name)@name=name end def say UHello puts"hello,#{@name}"end end

03

of 03

为什么要手动定义Setters和getter?

为什么要手动定义安装器?为什么每次不使用attr方法?因为它们打破了封装。封装是这样的原则,即没有外部实体应该可以不受限制地访问对象的内部状态。应使用防止用户损坏对象内部状态的界面访问所有内容。使用上述方法,我们'在封装壁上打了一个大洞,并**允许为名称设置任何东西,甚至显然是无效的名称。

您经常看到的一件事是attrëu reader将用于快速定义getter,但将定义自定义设置器,因为对象的内部状态通常希望直接从内部状态读取。然后手动定义安装器并检查以确保设置的值是有意义的。或者,也许更常见的是,根本没有定义setter。类函数中的其他方法以某种其他方式在getter后面设置实例变量。

我们现在可以添加一个年龄,并正确实现名称属性。可以在constructor方法中设置age属性,使用agegetter读取,但仅使用haveëbroady方法操作,这将增加年龄。name属性具有正常的getter,但setter确保名称大写,并采用Firstname Lastname的形式。

#!/usr/bin/env ruby类Person def初始化(姓名,年龄)self.name=name@age=age end attr#reader:name,:age def name=(newname)如果newname=〜/^[A-Z][A-Z]+[A-Z]+$/@name=new#name-else"'#{new#name}'不是有效名称!"结束定义有_生日放置"生日快乐#{@name}!"@age+=1 end def whoami put"你是#{@name},age#{@age}"end end p=人。新("Alice Smith",23)#谁是我?p、 whoami#她结婚了p.name="Alice Brown"#她试图成为一个偏心的音乐家p.name="A"#但失败#她有点老了p.Harve#生日#我再次是谁?p、 whoami