diff --git a/src/SUMMARY.md b/src/SUMMARY.md
index db3d81a..784d46a 100644
--- a/src/SUMMARY.md
+++ b/src/SUMMARY.md
@@ -94,5 +94,6 @@
- [面向对象](ch17-00-oop.md)
- [什么是面向对象](ch17-01-what-is-oo.md)
+ - [trait对象](ch17-02-trait-objects)
\ No newline at end of file
diff --git a/src/ch17-02-trait-objects.md b/src/ch17-02-trait-objects.md
new file mode 100644
index 0000000..0460caf
--- /dev/null
+++ b/src/ch17-02-trait-objects.md
@@ -0,0 +1,408 @@
+## 为使用不同类型的值而设计的Trait对象
+
+> [ch17-02-trait-objects.md](https://github.com/rust-lang/book/blob/master/second-edition/src/ch17-02-trait-objects.md)
+>
+> commit 872dc793f7017f815fb1e5389200fd208e12792d
+
+ 在第8章,我们谈到了vector的局限是vectors只能存储同种类型的元素。我们在Listing 8-1有一个例子,其中定义了一个`SpreadsheetCell` 枚举类型,可以存储整形、浮点型和text,这样我们就可以在每个cell存储不同的数据类型了,同时还有一个代表一行cell的vector。当我们的代码编译的时候,如果交换地处理的各种东西是固定的类型是已知的,那么这是可行的。
+
+```
+
+```
+
+有时,我们想我们使用的类型集合是可扩展的,可以被使用我们的库的程序员扩展。比如很多图形化接口工具有一个条目列表,从这个列表迭代和调用draw方法在每个条目上。我们将要创建一个库crate,包含称为`rust_gui`的CUI库的结构体。我们的GUI库可以包含一些给开发者使用的类型,比如`Button`或者`TextField`。使用`rust_gui`的程序员会创建更多可以在屏幕绘图的类型:一个程序员可能会增加`Image`,另外一个可能会增加`SelectBox`。我们不会在本章节实现一个完善的GUI库,但是我们会展示如何把各部分组合在一起。
+
+当要写一个`rust_gui`库时,我们不知道其他程序员要创建什么类型,所以我们无法定义一个`enum`来包含所有的类型。我们知道的是`rust_gui`需要有能力跟踪所有这些不同类型的大量的值,需要有能力在每个值上调用`draw`方法。我们的GUI库不需要确切地知道当调用`draw`方法时会发生什么,只要值有可用的方法供我们调用就可以。
+
+在有继承的语言里,我们可能会定义一个名为`Component`的类,该类上有一个`draw`方法。其他的类比如`Button`、`Image`和`SelectBox`会从`Component`继承并继承`draw`方法。它们会各自覆写`draw`方法来自定义行为,但是框架会把所有的类型当作是`Component`的实例,并在它们上调用`draw`。
+
+## 定义一个带有自定义行为的Trait
+
+不过,在Rust语言中,我们可以定义一个名为`Draw`的trait,其上有一个名为`draw`的方法。我们定义一个带有*trait对象*的vector,绑定了一种指针的trait,比如`&`引用或者一个`Box`智能指针。
+
+我们提到,我们不会调用结构体和枚举的对象,从而区分于其他语言的对象。在结构体的数据或者枚举的字段和`impl`块中的行为是分开的,而其他语言则是数据和行为被组合到一个概念里。Trait对象更像其他语言的对象,在这种场景下,他们组合了由指针组成的数据到实体对象,该对象带有在trait中定义的方法行为。但是,trait对象是和其他语言是不同的,因为我们不能向一个trait对象增加数据。trait对象不像其他语言那样有用:它们的目的是允许从公有的行为上抽象。
+
+trait定义了在给定场景下我们所需要的行为。在我们会使用一个实体类型或者一个通用类型的地方,我们可以把trait当作trait对象使用。Rust的类型系统会保证我们为trait对象带入的任何值会实现trait的方法。我们不需要在编译阶段知道所有可能的类型,我们可以把所有的实例统一对待。Listing 17-03展示了如何定义一个名为`Draw`的带有`draw`方法的trait。
+
+Filename: src/lib.rs
+
+```rust
+pub trait Draw {
+ fn draw(&self);
+}
+```
+
+Listing 17-3:`Draw` trait的定义
+
+
+
+因为我们已经在第10章讨论过如何定义trait,你可能比较熟悉。下面是新的定义:Listing 17-4有一个名为`Screen`的结构体,里面有一个名为`components`的vector,`components`的类型是Box。`Box`是一个trait对象:它是一个任何`Box`内部的实现了`Draw`trait的类型的替身。
+
+Filename: src/lib.rs
+
+```rust
+# pub trait Draw {
+# fn draw(&self);
+# }
+#
+pub struct Screen {
+ pub components: Vec>,
+}
+```
+
+Listing 17-4: 定义一个`Screen`结构体,带有一个含有实现了`Draw`trait的`components` vector成员
+
+
+
+在`Screen`结构体上,我们将要定义一个`run`方法,该方法会在它的`components`上调用`draw`方法,如Listing 17-5所示:
+
+Filename: src/lib.rs
+
+```rust
+# pub trait Draw {
+# fn draw(&self);
+# }
+#
+# pub struct Screen {
+# pub components: Vec>,
+# }
+#
+impl Screen {
+ pub fn run(&self) {
+ for component in self.components.iter() {
+ component.draw();
+ }
+ }
+}
+```
+
+Listing 17-5:在`Screen`上实现一个`run`方法,该方法在每个组件上调用`draw`方法
+
+
+这是区别于定义一个使用带有trait绑定的通用类型参数的结构体。通用类型参数一次只能被一个实体类型替代,而trait对象可以在运行时允许多种实体类型填充trait对象。比如,我们已经定义了`Screen`结构体使用通用类型和一个trait绑定,如Listing 17-6所示:
+
+Filename: src/lib.rs
+
+```rust
+# pub trait Draw {
+# fn draw(&self);
+# }
+#
+pub struct Screen {
+ pub components: Vec,
+}
+
+impl Screen
+ where T: Draw {
+ pub fn run(&self) {
+ for component in self.components.iter() {
+ component.draw();
+ }
+ }
+}
+```
+
+Listing 17-6: 一种`Screen`结构体的替代实现,它的`run`方法使用通用类型和trait绑定
+
+
+这个例子只能使我们有一个`Screen`实例,这个实例有一个组件列表,所有的组件类型是`Button`或者`TextField`。如果你有同种的集合,那么可以优先使用通用和trait绑定,这是因为为了使用具体的类型,定义是在编译阶段是单一的。
+
+而如果使用内部有`Vec>` trait对象的列表的`Screen`结构体,`Screen`实例可以同时包含`Box