> For the complete documentation index, see [llms.txt](https://overleaf-pro.ayaka.space/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://overleaf-pro.ayaka.space/latex/zh-cn/lei-wen-jian/04-writing-your-own-class.md).

# 编写你自己的类

有时，自定义文档的最佳选择是从头编写一个新类。本文解释了新类所需的主要结构和命令。

## 引言

在编写新类之前，首先要做的是确定你是否真的需要新类。建议先 [在 CTAN（Comprehensive TeX Archive Network，综合 TeX 归档网络）上搜索](http://www.ctan.org/ctan-portal/search/) 并查看是否已经有人创建了与你所需文档类类似的东西。

另一个需要牢记的重要事情是 [宏包与类的区别](/latex/zh-cn/lei-wen-jian/01-understanding-packages-and-class-files.md)。选错会影响最终产品的灵活性。

## 总体结构

所有类文件的结构大致可分为以下四个部分：

* ***标识***。该文件声明自身是一个使用 LaTeX2ε 语法编写的类。
* ***预备声明***。这里导入所需的外部宏包和类。此外，在文件的这一部分还会编写由所声明选项所需的命令和定义。
* ***选项***。该类声明并处理选项。
* ***更多声明***。类的主体部分。类所做的几乎所有事情都在这里定义。

在接下来的小节中，将给出更详细的结构说明和一个可运行的示例， *exampleclass.cls*，将会展示出来。

### 标识

所有类都必须包含两个简单命令：

```latex
\NeedsTeXFormat{LaTeX2e}
\ProvidesClass{exampleclass}[2014/08/16 Example LaTeX class]
```

命令 `\NeedsTeXFormat{LaTeX2e}` 用于设置该类所使用的 LaTeX 版本。此外，还可以在方括号中添加日期，以指定所需的最早发行日期。

命令 `ProvidesClass{exampleclass}[...]` 将该类标识为 *exampleclass* ，并且在方括号中包含发布日期和一些附加信息。日期应采用 YYYY/MM/DD 形式

[在 Overleaf 中打开一个编写类的示例](https://www.overleaf.com/project/new/template/19419?id=65524436\&templateName=An+example+of+writing+a+LaTeX+class\&latexEngine=\&texImage=texlive-full%3A2020.1\&mainFile=)

### 预备声明

大多数类会扩展和定制现有类，并且通常还需要一些外部宏包才能工作。下面在示例类中添加了一些更多代码 `exampleclass.cls`.

```latex
\NeedsTeXFormat{LaTeX2e}
\ProvidesClass{exampleclass}[2014/08/16 Example LaTeX class]

\newcommand{\headlinecolor}{\normalcolor}
\LoadClass[twocolumn]{article}
\RequirePackage{xcolor}
\definecolor{slcolor}{HTML}{882B21}
```

这一部分中的命令要么初始化一些稍后用于管理选项的参数，要么导入外部文件。

命令 `\LoadClass[twocolumn]{article}` 加载该类 `article` 并带有附加参数 `twocolumn`。因此，标准 `article` 类中的所有命令都将自动可用于 **示例** 该类，但文档将以双栏格式排版。

`\RequirePackage` 与众所周知的 `\usepackage`非常相似，在方括号中添加可选参数也同样可行。唯一的区别是， `\usepackage` 不能在 `\documentclass` 命令之前使用。强烈建议在编写新宏包或类时使用 `\RequirePackage` 在编写新类或宏包时。

[在 Overleaf 中打开一个编写类的示例](https://www.overleaf.com/project/new/template/19419?id=65524436\&templateName=An+example+of+writing+a+LaTeX+class\&latexEngine=\&texImage=texlive-full%3A2020.1\&mainFile=)

### 选项

为了使类具有一定的灵活性，一些额外选项非常有用。文件中的下一部分 `exampleclass.cls` 处理传递给 document class 命令的参数。我们还将 `\LoadClass` 更改为 *后添加浮动位置修饰符* 在处理选项时，以便在 .tex 文件中设置的选项可以传递给基类。

```latex
\NeedsTeXFormat{LaTeX2e}
\ProvidesClass{exampleclass}[2014/08/16 Example LaTeX class]

\newcommand{\headlinecolor}{\normalcolor}
\RequirePackage{xcolor}
\definecolor{slcolor}{HTML}{882B21}

\DeclareOption{onecolumn}{\OptionNotUsed}
\DeclareOption{green}{\renewcommand{\headlinecolor}{\color{green}}}
\DeclareOption{red}{\renewcommand{\headlinecolor}{\color{slcolor}}}
\DeclareOption*{\PassOptionsToClass{\CurrentOption}{article}}
\ProcessOptions\relax
\LoadClass[twocolumn]{article}
```

这里有四个主要命令用于处理传递给该类的选项。

命令 `\DeclareOption{}{}` 用于处理给定选项。它接受两个参数，第一个是选项名称，第二个是在传入该选项时要执行的代码。

命令 `\OptionNotUsed` 将在编译器和日志中打印一条消息，该选项将不会被使用。在这种情况下，文档被设置为双栏，如果用户试图将其改为单栏，这将不起作用，该选项将被忽略。

命令 `\Declareoption*{}` 处理每一个未明确定义的选项。它只接受一个参数，即在传入未知选项时要执行的代码。在这种情况下，它将运行下一条命令：

`\PassOptionsToClass{}{}`。将第一对花括号中的选项传递给第二对花括号中指定的文档类。在示例中，所有未知选项都将传递给 **article** 文档类。

`\CurrentOption` 存储正在某一时刻处理的类选项名称。

命令 `\ProcessOptions\relax` 执行每个选项的代码，并且必须放在所有选项处理命令之后。该命令还有一个带星号的版本，它会按照调用命令所指定的精确顺序执行这些选项。

在示例中，如果选项 `red` 或 `绿色` 传递给文档后，标题和各节所使用的字体将设置为相应的颜色。名为 `slcolor` 定义于 [预备声明](#preliminary-declaration) 之后导入的 `xcolor` 宏包。

[在 Overleaf 中打开一个编写类的示例](https://www.overleaf.com/project/new/template/19419?id=65524436\&templateName=An+example+of+writing+a+LaTeX+class\&latexEngine=\&texImage=texlive-full%3A2020.1\&mainFile=)

### 更多声明

在这一部分中，大部分命令都会出现。在“exampleclass.cls”中，设置了页面尺寸、标题字体大小、正文和各节的字体大小。下面你可以看到完整的类文件。

```latex
\NeedsTeXFormat{LaTeX2e}
\ProvidesClass{exampleclass}[2014/08/16 Example LaTeX class]

\newcommand{\headlinecolor}{\normalcolor}
\RequirePackage{xcolor}
\definecolor{slcolor}{HTML}{882B21}

\DeclareOption{onecolumn}{\OptionNotUsed}
\DeclareOption{green}{\renewcommand{\headlinecolor}{\color{green}}}
\DeclareOption{red}{\renewcommand{\headlinecolor}{\color{slcolor}}}
\DeclareOption*{\PassOptionsToClass{\CurrentOption}{article}}
\ProcessOptions\relax
\LoadClass[twocolumn]{article}

\renewcommand{\maketitle}{%
    \twocolumn[%
        \fontsize{50}{60}\fontfamily{phv}\fontseries{b}%
        \fontshape{sl}\selectfont\headlinecolor
        \@title
        \\medskip
        ]%
}

\renewcommand{\section}{%
    \@startsection
    {section}{1}{0pt}{-1.5ex plus -1ex minus -.2ex}%
    {1ex plus .2ex}{\large\sffamily\slshape\headlinecolor}%
}

\renewcommand{\normalsize}{\fontsize{9}{10}\selectfont}
\setlength{\textwidth}{17.5cm}
\setlength{\textheight}{22cm}
\setcounter{secnumdepth}{0}
```

要理解其余命令，请参见 [参考指南](#reference-guide) 以及 [进一步阅读部分](#further-reading).

示例中的最后四条命令展示了所有类都必须包含的四项内容：

* 的定义 `normalsize`。设置默认的 [字号](/latex/zh-cn/zi-ti/01-font-sizes-families-and-styles.md).
* 一个默认值，用于 [`textwidth`](/latex/zh-cn/ge-shi-hua/07-page-size-and-margins.md)
* 一个默认值，用于 [`textheight`](/latex/zh-cn/ge-shi-hua/07-page-size-and-margins.md)
* 关于……的设置 [页码编号](/latex/zh-cn/ge-shi-hua/03-page-numbering.md).

下面是一个使用该类的文档 *exampleclass.cls*.

```latex
\documentclass[red]{exampleclass}
\usepackage[utf8]{inputenc}
\usepackage[english]{babel}

\usepackage{blindtext}

\title{Example to show how classes work}
\author{Team Learn ShareLaTeX}
\date{August 2014}

\begin{document}

\maketitle

\noindent
下面先从一个简单的可运行示例开始。

\blindtext

\section{引言}

蒙提霍尔问题...

\section{The same thing}

蒙提...
```

![WrittingClassesEx1.png](/files/cb993fb74303dacf169c74b3f3ec36fcb8cd7172)

请注意，这里的第一条命令是

```latex
\documentclass[red]{exampleclass}
```

[在 Overleaf 中打开一个编写类的示例](https://www.overleaf.com/project/new/template/19419?id=65524436\&templateName=An+example+of+writing+a+LaTeX+class\&latexEngine=\&texImage=texlive-full%3A2020.1\&mainFile=)

## 错误处理

在开发新类时，处理可能的错误非常重要，以便让用户知道出了什么问题。编译器中有四个主要命令用于报告错误。

* `\ClassError{*class-name*}{*error-text*}{*help-text*}`。它接受三个参数，每个都放在花括号中：类名、将要显示的错误文本（编译过程将暂停），以及当用户因错误而导致编译暂停时按下“h”后将打印的帮助文本。
* `\ClassWarning{*class-name*}{*warning-text*}`。在这种情况下，文本会显示出来，但编译过程不会停止。它会显示警告发生的行号。
* `\ClassWarningNoLine{*class-name*}{*warning-text*}`。其作用与前一个命令相同，但不会显示警告发生的行号。
* `\ClassInfo{*class name*}{*info-text*}`。在这种情况下，第二个参数中的信息只会打印到转录文件中，并包含行号。

[在 Overleaf 中打开一个编写类的示例](https://www.overleaf.com/project/new/template/19419?id=65524436\&templateName=An+example+of+writing+a+LaTeX+class\&latexEngine=\&texImage=texlive-full%3A2020.1\&mainFile=)

## 参考指南

**类和宏包中常用命令列表**

* `\newcommand{*name*}{*definition*}`。定义一个 [新命令](/latex/zh-cn/ming-ling/01-commands.md#defining-a-new-command)，第一个参数是新命令的名称，第二个参数是该命令将执行的内容。
* `\renewcommand{}{}`。与 `\newcommand` 相同，但会覆盖已有命令。
* `\providecommand{}{}`。其作用与 `\newcommand` 相同，但如果该命令已经被定义，它会被静默忽略。
* `\CheckCommand{}{}`。语法与 `\newcommand`，但它会检查该命令是否存在以及是否具有预期的定义；如果该命令不是所期望的那样，LaTeX 会显示警告 `\CheckCommand` 所期望的那样，LaTeX 会显示警告。
* `\setlength{}{}`。将第一个参数所代表的元素长度设置为第二个参数写出的值。
* `\mbox{}`。创建一个包含花括号中所写元素的盒子。
* `\fbox{}`。与 `\mbox`，但会在内容周围实际打印一个框。

## 进一步阅读

更多信息请参见

* [理解宏包和类文件](/latex/zh-cn/lei-wen-jian/01-understanding-packages-and-class-files.md)
* [编写你自己的宏包](/latex/zh-cn/lei-wen-jian/03-writing-your-own-package.md)
* [命令](/latex/zh-cn/ming-ling/01-commands.md) 和 [环境](/latex/zh-cn/ming-ling/02-environments.md)
* [LaTeX 中的长度](/latex/zh-cn/ge-shi-hua/01-lengths-in-latex.md)
* [在 LaTeX 中使用颜色](/latex/zh-cn/ge-shi-hua/13-using-colors-in-latex.md)
* [大型项目中的管理](/latex/zh-cn/wen-dang-jie-gou/07-management-in-a-large-project.md)
* [面向类和宏包编写者的 LaTeX2ε](http://www.latex-project.org/guides/clsguide.pdf)
* [关于 tex 编程的注记](http://pgfplots.sourceforge.net/TeX-programming-notes.pdf)
* [少于小时的分钟：使用 LaTeX 资源](https://tug.org/pracjourn/2005-4/hefferon/hefferon.pdf)
* [The LaTeX Companion. 第二版](http://ptgmedia.pearsoncmg.com/images/9780201362992/samplepages/0201362996.pdf)


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## 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, and the optional `goal` query parameter:

```
GET https://overleaf-pro.ayaka.space/latex/zh-cn/lei-wen-jian/04-writing-your-own-class.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

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.
