> For the complete documentation index, see [llms.txt](https://kelby.gitbook.io/rails-beginner-s-guide/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://kelby.gitbook.io/rails-beginner-s-guide/activerecord_association_achitecture/inheritance.md).

# Inheritance 单表继承

**单表继承** 一个或多个 Model 继承于另一个 Model，并且最终它们用的是同一张表。

我们会遇到这样的情况：

Employee 有 manager 和 developer\
&#x20;Computer 有 pc 和 mac

有时候，需要把它区分对待；有时候，又要对它们一视同仁。

设计表和 model 时，用得比较多的是"两张类似的表，两个类似的 model" 还是 "一张表，一个 model，一个用于标识的字段"，再或者是第 3 种选择，也就是这里要讲的"STI(单表继承)"。

一般说来，单表继承通常用于：属性一样，但行为不一致。

## 是什么？

单表，就是在数据库你只需要一张表。\
&#x20;继承，就是你的 model 之间存在着继承关系。

上面的例子中：\
&#x20;我们可以只用 employees 表，却有 model Manager 和 model Developer，它们都继承于 Employee.\
&#x20;我们可以只用 computers 表，却有 model Pc 和 model Mac，它们都继承于 Computer.

## 选择

1. 各子模块属性是一样的。这里要从"面向对象"的角度去看，而不是简单的'属性一样'就能使用。
2. 需要把这些子模块代表的数据放在一想显示或者说做聚合吗？如果需要的话，那么使用 STI 是比较好的选择。因为从性能上来说，即使优化做得再好，跨表操作，也不如在一个表里操作，来得简单、高效。
3. 和第 1 条有点类似，它们属性是一样的，只是行为不一致而矣。如果只是大部分属性一样，那么可以考虑一下"多态关联"。

实际使用过程中，单表继承在某些方面提供了方便(比如：自动设置 type)，但同时也会造成麻烦(比如：多个 model)。同样的，使用"两张类似的表，两个类似的 model" 或 "一张表，一个 model，一个用于标识的字段"或其它手段，也会有自己的问题。

这些方法都有利有弊，选择时，我们尽量选择利大于弊的那一种吧。

## 使用

单表继承默认使用 `type` 做为标识字段，在表里面新增字段即可，当然，也可以用【Model Schema】里的 `inheritance_column` 自定义标识字段。创建相应对象时，会根据所使用的模块名自动设置它的值。

```ruby
class Company < ActiveRecord::Base
  # ...
end

class Firm < Company
  # ...
end

class Client < Company
  # ...
end
```
