# 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
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://kelby.gitbook.io/rails-beginner-s-guide/activerecord_association_achitecture/inheritance.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
