第93.10款实施说明第 93 章面向对象编程TikZ & PGF 手册 3.0.1a 版指出(重点是我加上的):
调用方法时,在调用方法之前会执行一些代码,将存储当前对象 ID 的全局计数器设置为被调用对象的对象 ID。调用方法之后会插入一些代码,将全局计数器恢复为其原始值。此操作无需作用域,因此
\expandafter
需要一些巧妙的技巧。请注意,由于此过程,\pgfutil@ifnextchar
你不能在方法末尾使用命令。
\pgfutil@ifnextchar
那些不能在方法末尾使用的命令如何描述?此外还\pgfutil@ifnextchar
应该避免使用哪些命令?
或者,我可以遵循一些惯例来消除这种担忧吗?例如,如果我用 结束所有方法\relax
,或者如果我将所有方法主体包含在 TeX 组中。
答案1
应避免在方法主体末尾使用那些在输入流中前瞻的命令,例如\futurelet
,或者更一般地说,任何假设扩展方法主体后面跟着方法调用之后的文本的命令。原因是 pgf 的面向对象编程模块在方法主体之后(以及方法主体之前)将一些簿记代码插入到输入流中。
为了更详细地解释这一点,让我们比较一下方法调用的扩展方式和常规宏的扩展方式。
假设输入流如下所示:
\mac(arg)<rest of the input stream>
其中\mac
指定一个常规宏:
\def\mac(#1){<replacement text with #1>}
以上内容将扩展如下:
<replacement text with #1 substituted by 'arg'><rest of the input stream>
特别是, 的第一个标记<rest of the input stream>
紧跟在\mac
的替换文本之后。
但是,如果输入流如下所示:
\obj.meth(arg)<rest of the input stream>
其中\obj
是类 的对象句柄C
,meth
是 中定义的方法的名称C
:
\pgfooclass{C}{... \method meth(#1){<method body>} ...}
那么上述代码将扩展如下(参见中的宏\pgfoo@caller
和):\pgfoo@caller@cont
<pgf install dir>/modules/pgfoomodule.code.tex
<oo bookkeeping>%
\pgfoothis@count<\obj's id>\relax% (*)
<method body with #1 substituted by 'arg'>%
\pgfoothis@count<\pgfoothis@count's value just before (*)>\relax%
<rest of the input stream>
其中\pgfoothis@count
,对象 ID 计数器在每次创建对象时都会递增,如手册的“实施说明”部分(93.10)中第一个要点所述。
特别是, 的第一个标记<rest of the input stream>
并不紧跟 的\obj.meth
主体。
从中可以看出,您还应该确保当方法执行完毕时,控制序列\pgfoothis@count
不会\relax
被重新定义。