> For the complete documentation index, see [llms.txt](https://ayakaleaf-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://ayakaleaf-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` 处理传递给文档类命令的参数。我们还将 `\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` 或 `green` 传递给文档后，标题和各节所用的字体将设置为相应的颜色。名为 `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{Introduction}

蒙提霍尔问题……

\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*}`。在这种情况下，第二个参数中的信息只会打印到 transcript 文件中，包括行号。

[在 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` 所期望的。
* `\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. Second edition](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://ayakaleaf-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.
