## 14.结构和 OpenStruct 好的,在前面的章节中,我们介绍了类,现在让我们简单地看一下名为 struct <sup class="footnote">[ [35](#_footnotedef_35 "View footnote.") ]</sup> 的简单事物。 输入以下程序并执行 ```rb # struct_start.rb person = Struct.new :name, :age p = person.new p.name = "Karthik" p.age = 30 puts "Hello, I am #{p.name}, age #{p.age}" ``` 输出量 ```rb Hello, I am Karthik, age 30 ``` 好了,现在让我们看看它是如何工作的。 首先,你将使用此语句创建新的`Struct`类型 ```rb Struct.new :name, :age ``` 现在,你要命名它,以便可以使用它,将其命名为`person` ```rb person = Struct.new :name, :age ``` 命名后,此变量`person`的作用类似于`class`,你可以像这样声明它的新实例 ```rb p = person.new ``` 在上面的语句中,`p`是 person 的实例。 现在我们可以使用以下语句分配`p`的`:name`和`:age` ```rb p.name = "Karthik" p.age = 30 ``` 然后你可以打印数据,如下所示 ```rb puts "Hello, I am #{p.name}, age #{p.age}" ``` 而已。 在不使用`class`的情况下,你创建了一个数据结构并使用了它! 你不觉得它很棒吗? 并不是`person = Struct.new :name, :age`中的`person`应该是可变的(即以小写字母开头),但是它也可以像`Person`一样是常量。 这就是这里的下一段代码中的确切内容 ```rb # struct_constant.rb Person = Struct.new :name, :age p = Person.new p.name = "Karthik" p.age = 30 puts "Hello, I am #{p.name}, age #{p.age}" ``` Output ```rb Hello, I am Karthik, age 30 ``` 所以在这些行中 ```rb Person = Struct.new :name, :age p = Person.new ``` 我们已经将`Person`与大写字母 P 结合使用,并且代码有效! 如果你担心在上一个程序中需要输入很多字符,可以如下所示将其缩短。 请看下面的代码。 ```rb # struct_one_line.rb person = Struct.new :name, :age p = person.new "Karthik", 30 puts "Hello, I am #{p.name}, age #{p.age}" ``` Output ```rb Hello, I am Karthik, age 30 ``` 我们得到相同的输出,但是在这一行中 ```rb p = person.new "Karthik", 30 ``` 我们设法消除了这两条线 ```rb p.name = "Karthik" p.age = 30 ``` 如果你注意到正确的话,`p = person.new "Karthik", 30`看起来不是类中的构造函数吗? 并非`Struct`仅限于其属性数据结构。 你可以具有一个`Struct`实例可以调用的功能,如下面的程序所示。 输入并执行。 ```rb include:code/struct_about_me.rb[] ``` Output ```rb Hello, I am Karthik, age 30 ``` 如你所见,在 Struct 的`do end`块之间定义了一个名为`about_me`的函数。 我们在此行`p = person.new "Karthik", 30`中声明一个人`p`,然后像`puts p.about_me`这样调用`p`上的`about_me`函数,程序运行正常。 你还必须注意,我们可以将参数传递给 struct 中的函数,但是由于我的懒惰,我没有显示该示例。 现在让我们看看如何以错误的方式进行结构化。 在下面输入程序并执行 ```rb # struct_wrong.rb person = Struct.new :name, :age p = person.new p.name = "Karthik" p.age = 30 p.profession = "Engineer" puts "Hello, I am #{p.name}, age #{p.age}, and I am on a #{p.profession}" ``` Output ```rb struct_wrong.rb:7:in `
': undefined method `profession=' for # (NoMethodError) ``` 如果你得到如上所示的输出,则表明你正确键入了该程序。 问题出在`p.profession = "Engineer"`行中,我们正在将数据分配给尚未在结构`person = Struct.new :name, :age`中声明的名为职业的属性。 因此会引发错误。 为了避免这些事情,你可以使用下面的程序中所示的 Open Struct ```rb # open_struct.rb require 'ostruct' p = OpenStruct.new p.name = "Karthik" p.age = 30 puts "Hello, I am #{p.name}, age #{p.age}" ``` Output ```rb Hello, I am Karthik, age 30 ``` Open Struct 类似于 Struct,但是它没有预定义其数据结构或属性。