Author: Kirill Müller, Hadley Wickham

# Extending tibble

#### Kirill Müller, Hadley Wickham

Tibbles are S3 objects of class `c("tbl_df", "tbl", "data.frame")`. This means that they inherit their behavior from the `"data.frame"` class and add two subclasses `"tbl"` and `"tbl_df"`. The pillar and tibble packages provide methods for `"tbl"` and `"tbl_df"`, respectively. Package authors and programmers can implement subclasses that extend either `"tbl_df"` (and its subclasses) or only `"tbl"` to provide custom behavior for tibble-like objects. In addition, vectors classes can be implemented from scratch or on top of existing classes, to be used as columns. This article provides links to the various customization points that help you avoiding reimplement existing behavior, and describes the difference between `"tbl"` and `"tbl_df"`.

Read more in the second edition of Advanced R:

- about the internal representation of data frames and tibbles in the Lists and Data frames and tibbles sections of the Vectors chapter,
- about R’s S3 object-oriented system in the S3 chapter.

## Topics documented elsewhere

- Change or tweak the way a tibble prints: `vignette("extending", package = "pillar")`

- Change or tweak the way a column type is printed in a tibble: `vignette("pillar", package = "vctrs")`

- Implement a new column data type: `vignette("s3-vector", package = "vctrs")`

- Making your tibble subclass work well with dplyr: `?dplyr::dplyr_extending`

## Data frame subclasses

    library(tibble)

For tibble >= 3.0.0, the `"tbl"` class is responsible for printing, while the `"tbl_df"` class adds tibble’s sturdy subsetting and subset assignment behavior (see `vignette("invariants")` for details). This means that a data frame class that would like to (mostly) print like a tibble but keep the behavior from base R’s data frames can inherit from `c("tbl", "data.frame")` or just from `"tbl"`. An example is the `"tbl_sql"` class in the dbplyr package that is used to implement lazy database tables.

### Tibble example

    my_tbl_df <- new_tibble(
      list(a = 1:3, b = 2:4),
      class = "my_tbl_df"
    )

    tbl_sum.my_tbl_df <- function(x, ...) {
      c(
        "My custom tibble" = "Some info about it",
        NextMethod()
      )
    }

    my_tbl_df

    ## # My custom tibble: Some info about it
    ## # A tibble:         3 × 2
    ##       a     b
    ##   <int> <int>
    ## 1     1     2
    ## 2     2     3
    ## 3     3     4

    my_tbl_df[, "a"]

    ## # My custom tibble: Some info about it
    ## # A tibble:         3 × 1
    ##       a
    ##   <int>
    ## 1     1
    ## 2     2
    ## 3     3

### Data frame example

    my_tbl <- vctrs::new_data_frame(
      list(a = 1:3, b = 2:4),
      class = c("my_tbl", "tbl")
    )

    tbl_sum.my_tbl <- function(x, ...) {
      c(
        "My custom data frame" = "Some info about it",
        NextMethod()
      )
    }

    my_tbl

    ## # My custom data frame: Some info about it
    ## # A data frame:         3 × 2
    ##       a     b
    ##   <int> <int>
    ## 1     1     2
    ## 2     2     3
    ## 3     3     4

    my_tbl[, "a"]

    ## [1] 1 2 3