You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: NEWS.md
+1Lines changed: 1 addition & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,4 +1,5 @@
1
1
# roxygen2 (development version)
2
+
*`vignette("rd-other")` now includes improved advice for documenting S3 generics, classes, and methods, including how to use the new [doclisting](https://doclisting.r-lib.org/) package to automatically list methods for a generic (#1513).
2
3
* Added initial support for S7 classes, generics, and methods (#1484).
3
4
* S7 generics are documented like regular functions.
4
5
* S7 classes are documented like regular functions, but you can use `@prop` to document additional properties that are not constructor parameters. If multiple classes share one page, use `@prop ClassName@prop_name description` to group properties by class.
- S3 **generics** are regular functions, so document them as such.
91
-
If necessary, include a section that provides additional details for developers implementing methods.
90
+
Documenting [S3 code](https://adv-r.hadley.nz/s3.html) well requires thinking about three things:
92
91
93
-
- S3 **classes** have no formal definition, so document the [constructor](https://adv-r.hadley.nz/s3.html#s3-constructor).
92
+
-**Generics**: mention that the function is a generic and list the
93
+
available methods.
94
+
-**Methods**: link back to the generic; only document individually
95
+
when the method has unique behavior or arguments.
96
+
-**Classes**: document the constructor.
94
97
95
-
- It is your choice whether or not to document S3 **methods**.
96
-
Generally, it's not necessary to document straightforward methods for common generics like `print()`.
97
-
(You should, however, always `@export` S3 methods, even internal ones).
98
+
### Generics
98
99
99
-
If your method is more complicated, you should document it by setting `@rdname` or `@describeIn`.
100
-
For complicated methods, you might document in their own file (i.e. `@name generic.class`; for simpler methods you might document with the generic (i.e. `@rdname generic)`.
101
-
Learn more about these tags in `vignette("reuse")`.
100
+
S3 **generics** are regular functions, so document them as such.
101
+
Export a generic if you want users to call it or other developers to
102
+
write methods for it. If the generic is internal, you don't need to
103
+
document it.
102
104
103
-
- Generally, roxygen2 will automatically figure out the generic that the method belongs to, and you should only need to use `@method` if there is ambiguity.
104
-
For example, is `all.equal.data.frame()` the `equal.data.frame` method for `all()`, or the `data.frame` method for `all.equal()`?.
105
-
If this happens to you, disambiguate with (e.g.) `@method all.equal data.frame`.
105
+
The documentation should mention that the function is a generic, because this
106
+
tells the reader that the behavior may vary depending on the input and that
107
+
they can write their own methods. For simple generics, you can do this
108
+
in the description:
109
+
110
+
```{r}
111
+
#| eval: false
112
+
113
+
#' Frobnpolicate an object
114
+
#'
115
+
#' @description
116
+
#' `frobnpolicate()` is an S3 generic that ..., with methods available for
For more complicated generics, you can use a `# Methods` section to
123
+
provide more detail:
124
+
125
+
```{r}
126
+
#| eval: false
127
+
128
+
#' Frobnpolicate an object
129
+
#'
130
+
#' @description
131
+
#' `frobnpolicate()` does ...
132
+
#'
133
+
#' # Methods
134
+
#' `frobnpolicate()` is an S3 generic with methods available for the following
135
+
#' classes:
136
+
#'
137
+
#' `r doclisting::methods_list("frobnpolicate")`
138
+
```
139
+
140
+
You might also want to include a section that provides additional details for developers implementing their own methods.
141
+
142
+
Both examples above use the [doclisting](https://doclisting.r-lib.org/)
143
+
package to automatically generate a list of methods, with links to their
144
+
help topics. These examples use [inline R code](reuse.html#inline-code) (`` `r ` ``), which generates the list at documentation time (i.e. when you run
145
+
`devtools::document()`). This only requires including doclisting in `Suggests`.
146
+
147
+
If you want the list to dynamically reflect all methods that are currently registered
148
+
(including methods registered by other packages), use an [inline Rd code](
149
+
reuse.html#inline-rd-code) block
150
+
(`` `Rd ` ``) instead:
151
+
152
+
```{r}
153
+
#| eval: false
154
+
155
+
#' `Rd doclisting::methods_list("frobnpolicate")`
156
+
```
157
+
158
+
Using `` `Rd ` `` requires doclisting in `Imports`, and you'll need a dummy call to eliminate the `R CMD check` NOTE about unused imports:
159
+
160
+
```{r}
161
+
#| eval: false
162
+
163
+
ignore_unused_imports <- function() {
164
+
doclisting::methods_list
165
+
}
166
+
```
167
+
168
+
169
+
### Classes
170
+
171
+
S3 **classes** have no formal definition, so document the [constructor](https://adv-r.hadley.nz/s3.html#s3-constructor).
172
+
Export the constructor if you want users to create instances of your
173
+
class or other developers to extend it (e.g. by creating subclasses).
174
+
Internal constructors don't need documentation.
175
+
176
+
Note that you don't need to list methods for a class: in S3, methods
177
+
belong to generics, not to classes. Users should look at the generic's
178
+
help page to learn about available methods.
179
+
180
+
### Methods
181
+
182
+
It is your choice whether or not to document S3 **methods**.
183
+
Generally, it's not necessary to document straightforward methods for
184
+
common generics like `print()`. (You should, however, always `@export`
185
+
S3 methods, even internal ones.)
186
+
187
+
It's good practice, however, to document methods that have unique behavior or arguments. For example, the clock package documents the methods for
188
+
[`date_group()`](https://clock.r-lib.org/reference/date_group.html) on
189
+
their own pages ([Date](https://clock.r-lib.org/reference/date-group.html),
190
+
[POSIXt](https://clock.r-lib.org/reference/posixt-group.html)) because the
191
+
methods accept different `precision` values and have type-specific return
192
+
value semantics and examples. The generic page serves only as a signpost
193
+
linking to the individual method pages.
194
+
195
+
When documenting a method, always include a link back to the generic
196
+
using `[generic_name()]` so the reader can easily find the full
197
+
documentation and other methods.
198
+
199
+
### Method disambiguation
200
+
201
+
Generally, roxygen2 will automatically figure out the generic that the
202
+
method belongs to, and you should only need to use `@method` if there
203
+
is ambiguity. For example, is `all.equal.data.frame()` the
204
+
`equal.data.frame` method for `all()`, or the `data.frame` method for
205
+
`all.equal()`? If this happens to you, disambiguate with (e.g.)
206
+
`@method all.equal data.frame`.
106
207
107
208
## S4
108
209
109
210
S4 **generics** are also functions, so document them as such.
211
+
Export a generic if you want users to call it or other developers to
212
+
write methods for it. If the generic is internal, you don't need to
213
+
document it.
110
214
111
215
Document **S4 classes** by adding a roxygen block before `setClass()`.
216
+
Export a class if you want users to create instances or other developers
217
+
to extend it (e.g. by creating subclasses). Internal classes don't need
Unlike S3 methods, all S4 methods must be documented.
234
+
Unlike S3 and S7 methods, all S4 methods must be documented.
128
235
You can document them in three places:
129
236
130
237
- In the class.
@@ -134,16 +241,98 @@ You can document them in three places:
134
241
Most appropriate if the generic uses multiple dispatches and you control it.
135
242
136
243
- In its own file.
137
-
Most appropriate if the method is complex.
138
-
or the either two options don't apply.
244
+
Most appropriate if the method is complex or the either two options don't apply.
139
245
140
-
Use either `@rdname` or `@describeIn` to control where method documentation goes.
141
-
See the next section for more details.
246
+
Use either `@rdname` or `@describeIn` to control where method documentation goes. See `vignette("reuse")` for more details.
142
247
143
248
## S7
144
249
250
+
Documenting S7 code well requires thinking about three things:
251
+
252
+
-**Generics**: mention that the function is a generic and list the
253
+
available methods.
254
+
-**Methods**: link back to the generic; only document individually
255
+
when the method has unique behavior or arguments.
256
+
-**Classes**: document the constructor.
257
+
258
+
### Generics
259
+
260
+
S7 **generics** are functions, so document them as such.
261
+
Export a generic if you want users to call it or other developers to
262
+
write methods for it. If the generic is internal, you don't need to
263
+
document it.
264
+
265
+
The documentation should mention that the function is a generic, because
266
+
this tells the reader that the behavior may vary depending on the input
267
+
and that they can write their own methods. For simple generics, you can
268
+
do this in the description:
269
+
270
+
```{r}
271
+
#| eval: false
272
+
273
+
#' Size of an object
274
+
#'
275
+
#' @description
276
+
#' `size()` is an S7 generic that determines the size of an object,
277
+
#' with methods available for the following classes:
278
+
#'
279
+
#' `r doclisting::methods_inline("size")`
280
+
#'
281
+
#' @param x An object.
282
+
#' @param ... Not used.
283
+
#' @returns A single number.
284
+
#' @export
285
+
size <- new_generic("size", "x")
286
+
```
287
+
288
+
For more complicated generics, you can use a `# Methods` section to
289
+
provide more detail:
290
+
291
+
```{r}
292
+
#| eval: false
293
+
294
+
#' Size of an object
295
+
#'
296
+
#' @description
297
+
#' `size()` determines the size of an object.
298
+
#'
299
+
#' # Methods
300
+
#' `size()` is an S7 generic with methods available for the following
301
+
#' classes:
302
+
#'
303
+
#' `r doclisting::methods_list("size")`
304
+
#'
305
+
#' @param x An object.
306
+
#' @param ... Not used.
307
+
#' @returns A single number.
308
+
#' @export
309
+
size <- new_generic("size", "x")
310
+
```
311
+
312
+
See the [S3 Generics section](#generics) above for more about using the
313
+
[doclisting](https://doclisting.r-lib.org/) package to automatically
314
+
generate method lists.
315
+
316
+
It's good practice to document the default method alongside the generic
317
+
using `@rdname`:
318
+
319
+
```{r}
320
+
#| eval: false
321
+
322
+
#' @rdname size
323
+
method(size, class_any) <- function(x, ...) {
324
+
length(x)
325
+
}
326
+
```
327
+
328
+
### Classes
329
+
145
330
S7 **classes** are constructor functions, so document them much like
146
-
you'd document any other function. Use `@param` to document the
331
+
you'd document any other function. Export a class if you want users to
332
+
create instances or other developers to extend it (e.g. by creating
333
+
subclasses). Internal classes don't need documentation.
334
+
335
+
Use `@param` to document the
147
336
constructor arguments (which correspond to class properties), and
148
337
`@returns` to describe the object that is returned. If the class has
149
338
additional properties that are not part of the constructor (e.g.
@@ -178,38 +367,24 @@ If multiple classes share one Rd page (via `@rdname`), you can prefix
178
367
the property name with the class name to group properties by class,
179
368
e.g. `@prop ClassName@prop_name description`.
180
369
181
-
S7 **generics** are also functions, so document them as such.
182
-
It's good practice to document the default method alongside the generic using `@rdname`:
370
+
### Methods
183
371
184
-
```{r}
185
-
#| eval: false
186
-
187
-
#' Size of an object
188
-
#'
189
-
#' An S7 generic for determining the size of an object. The default method
190
-
#' uses [length()], but other classes may have more specific implementations.
191
-
#'
192
-
#' @param x An object.
193
-
#' @param ... Not used.
194
-
#' @returns A single number.
195
-
#' @export
196
-
size <- new_generic("size", "x")
197
-
198
-
#' @rdname size
199
-
method(size, class_any) <- function(x, ...) {
200
-
length(x)
201
-
}
202
-
```
372
+
It is your choice whether or not to document S7 **methods**.
373
+
S7 methods are registered with `method(generic, class) <- fn`.
374
+
Generally, it's not necessary to document straightforward methods.
203
375
204
-
S7 **methods** are registered with `method(generic, class) <- fn`. You don't need to document methods, but you _may_ want to do so for particularly complicated implementations or methods with extra arguments.
205
-
If you do decided to document a method, give it its own roxygen block:
376
+
It's good practice, however, to document methods that have unique
377
+
behavior or arguments. If you do document a method, give it its own
378
+
roxygen block. When documenting a method, always include a link back to
379
+
the generic using `[generic_name()]` so the reader can easily find the
380
+
full documentation and other methods.
206
381
207
382
```{r}
208
383
#| eval: false
209
384
210
385
#' Size of a range
211
386
#'
212
-
#' The size of a range is its length.
387
+
#' The size of a range is its [size()], i.e. its length.
0 commit comments