Lists, Attributes, & S3

Lecture 04

Dr. Colin Rundel

Generic Vectors

Lists

Lists are the other vector data structure in R, they differ from atomic vectors in that they can contain a heterogeneous collection of R object (e.g. atomic vectors, functions, other lists, etc.).

list("A", c(TRUE,FALSE), (1:4)/2, list(TRUE, 1), function(x) x^2)
[[1]]
[1] "A"

[[2]]
[1]  TRUE FALSE

[[3]]
[1] 0.5 1.0 1.5 2.0

[[4]]
[[4]][[1]]
[1] TRUE

[[4]][[2]]
[1] 1


[[5]]
function(x) x^2

List Structure

Often we want a more compact representation of a complex object, the str() function is useful for this, particularly for lists.

str(c(1,2))
 num [1:2] 1 2
str(1:100)
 int [1:100] 1 2 3 4 5 6 7 8 9 10 ...
str("A")
 chr "A"
str( list(
  "A", c(TRUE,FALSE), 
  (1:4)/2, list(TRUE, 1), 
  sum
) )
List of 5
 $ : chr "A"
 $ : logi [1:2] TRUE FALSE
 $ : num [1:4] 0.5 1 1.5 2
 $ :List of 2
  ..$ : logi TRUE
  ..$ : num 1
 $ :function (..., na.rm = FALSE)  

Recursive lists

Lists can contain other lists, meaning they don’t have to be flat

str( list(1, list(2, list(3, 4), 5)) )
List of 2
 $ : num 1
 $ :List of 3
  ..$ : num 2
  ..$ :List of 2
  .. ..$ : num 3
  .. ..$ : num 4
  ..$ : num 5

List Coercion

By default a vector will be coerced to a list (as a list is more general) if needed

str( c(1, list(4, list(6, 7))) )
List of 3
 $ : num 1
 $ : num 4
 $ :List of 2
  ..$ : num 6
  ..$ : num 7
str( list(1, list(4, list(6, 7))) )
List of 2
 $ : num 1
 $ :List of 2
  ..$ : num 4
  ..$ :List of 2
  .. ..$ : num 6
  .. ..$ : num 7

We can coerce a list into an atomic vector using unlist() - the usual type coercion rules then apply to determine the resulting type.

unlist(list(1:3, list(4:5, 6)))
[1] 1 2 3 4 5 6
unlist( list(1, list(2, list(3, "Hello"))) )
[1] "1"     "2"     "3"     "Hello"

Named lists

Because of their more complex structure we often want to name the elements of a list (we can also do this with atomic vectors).

This can make accessing list elements more straight forward (and avoids the use of magic numbers)

str(list(A = 1, B = list(C = 2, D = 3)))
List of 2
 $ A: num 1
 $ B:List of 2
  ..$ C: num 2
  ..$ D: num 3

More complex names (i.e. non-valid object names) are allowed but must be quoted,

list("knock knock" = "who's there?")
$`knock knock`
[1] "who's there?"

Exercise 1

Represent the following JSON data as a list in R.

{
  "firstName": "John",
  "lastName": "Smith",
  "age": 25,
  "address": 
  {
    "streetAddress": "21 2nd Street",
    "city": "New York",
    "state": "NY",
    "postalCode": 10021
  },
  "phoneNumber": 
  [ {
      "type": "home",
      "number": "212 555-1239"
    },
    {
      "type": "fax",
      "number": "646 555-4567"
  } ]
}
05:00

NULL Values

NULLs

NULL is a special value within R that represents nothing - it always has length zero and a type and mode of "NULL" and cannot have any attributes.

NULL
NULL
typeof(NULL)
[1] "NULL"
mode(NULL)
[1] "NULL"
length(NULL)
[1] 0
c()
NULL
c(NULL)
NULL
c(1, NULL, 2)
[1] 1 2
c(NULL, TRUE, "A")
[1] "TRUE" "A"   

0-length coercion

0-length length coercion is a special case of length coercion when one of the arguments has length 0. In this special case the longer vector will have its length coerced to 0.

integer() + 1
numeric(0)
log(numeric())
numeric(0)
logical() | TRUE
logical(0)
character() > "M"
logical(0)

As a NULL values always have length 0, this rule will apply (note the types)

NULL + 1
numeric(0)
NULL | TRUE
logical(0)
NULL > "M"
logical(0)
log(NULL)
Error in log(NULL): non-numeric argument to mathematical function

NULLs and comparison

Given the previous issue, comparisons and conditionals with NULLs can be problematic.

x = NULL
if (x > 0)
  print("Hello")
Error in if (x > 0) print("Hello"): argument is of length zero
if (!is.null(x) & (x > 0))
  print("Hello")
Error in if (!is.null(x) & (x > 0)) print("Hello"): argument is of length zero
if (!is.null(x) && (x > 0))
  print("Hello")

Attributes

Attributes

Attributes are metadata that can be attached to objects in R. Some are special ( e.g. class, comment, dim, dimnames, names, …) as they change the behavior of the object(s).

Attributes are implemented as a named list that is attached to an object. They can be interacted with via the attr and attributes functions.

(x = c(L=1,M=2,N=3))
L M N 
1 2 3 
str(attributes(x))
List of 1
 $ names: chr [1:3] "L" "M" "N"
attr(x, "names")
[1] "L" "M" "N"
attr(x, "something")
NULL

Assigning attributes

The most commonly used / important attributes will usually have helper functions for getting and setting the attribute,

x
L M N 
1 2 3 
names(x) = c("Z","Y","X")
x
Z Y X 
1 2 3 
names(x)
[1] "Z" "Y" "X"
attr(x, "names") = c("A","B","C")
x
A B C 
1 2 3 
names(x)
[1] "A" "B" "C"

Helpers functions vs attr

names(x) = 1:3
x
1 2 3 
1 2 3 
attributes(x)
$names
[1] "1" "2" "3"
names(x) = c(TRUE, FALSE, TRUE)
x
 TRUE FALSE  TRUE 
    1     2     3 
attributes(x)
$names
[1] "TRUE"  "FALSE" "TRUE" 
attr(x, "names") = 1:3
x
1 2 3 
1 2 3 
attributes(x)
$names
[1] "1" "2" "3"

Factors

Factor objects are how R represents categorical data (e.g. a variable where there is a discrete set of possible outcomes).

(x = factor(c("Sunny", "Cloudy", "Rainy", "Cloudy", "Cloudy")))
[1] Sunny  Cloudy Rainy  Cloudy Cloudy
Levels: Cloudy Rainy Sunny
str(x)
 Factor w/ 3 levels "Cloudy","Rainy",..: 3 1 2 1 1
typeof(x)
[1] "integer"
mode(x)
[1] "numeric"
class(x)
[1] "factor"

Composition

A factor is just an integer vector with two attributes: class and levels.

x
[1] Sunny  Cloudy Rainy  Cloudy Cloudy
Levels: Cloudy Rainy Sunny
str(attributes(x))
List of 2
 $ levels: chr [1:3] "Cloudy" "Rainy" "Sunny"
 $ class : chr "factor"

We can build our own factor from scratch using attr(),

y = c(3L, 1L, 2L, 1L, 1L)
attr(y, "levels") = c("Cloudy", "Rainy", "Sunny")
attr(y, "class") = "factor"
y
[1] Sunny  Cloudy Rainy  Cloudy Cloudy
Levels: Cloudy Rainy Sunny

Building objects

The approach we just used is a bit clunky - generally the preferred method for construction an object with attributes from scratch is to use the structure function.

( y = structure(
    c(3L, 1L, 2L, 1L, 1L),
    levels = c("Cloudy", "Rainy", "Sunny"),
    class = "factor"
) )
[1] Sunny  Cloudy Rainy  Cloudy Cloudy
Levels: Cloudy Rainy Sunny
class(y)
[1] "factor"
is.factor(y)
[1] TRUE

Factors are integer vectors?

Knowing factors are stored as integers help explain some of their more interesting behaviors:

x+1
[1] NA NA NA NA NA
is.integer(x)
[1] FALSE
as.integer(x)
[1] 3 1 2 1 1
as.character(x)
[1] "Sunny"  "Cloudy" "Rainy"  "Cloudy" "Cloudy"
as.logical(x)
[1] NA NA NA NA NA

S3 Object System

class

The class attribute is an additional layer to R’s type hierarchy,

value typeof() mode() class()
TRUE logical logical logical
1 double numeric numeric
1L integer numeric integer
"A" character character character
NULL NULL NULL NULL
list(1, "A") list list list
factor("A") integer numeric factor
function(x) x^2 closure function function
+ builtin function function
[ special function function

S3 class specialization

x = c("A","B","A","C")
print( x )
[1] "A" "B" "A" "C"
print( factor(x) )
[1] A B A C
Levels: A B C
print( unclass( factor(x) ) )
[1] 1 2 1 3
attr(,"levels")
[1] "A" "B" "C"
print.default( factor(x) )
[1] 1 2 1 3

What’s up with print?

print
function (x, ...) 
UseMethod("print")
<bytecode: 0x1430cbd78>
<environment: namespace:base>
print.default
function (x, digits = NULL, quote = TRUE, na.print = NULL, print.gap = NULL, 
    right = FALSE, max = NULL, width = NULL, useSource = TRUE, 
    ...) 
{
    args <- pairlist(digits = digits, quote = quote, na.print = na.print, 
        print.gap = print.gap, right = right, max = max, width = width, 
        useSource = useSource, ...)
    missings <- c(missing(digits), missing(quote), missing(na.print), 
        missing(print.gap), missing(right), missing(max), missing(width), 
        missing(useSource))
    .Internal(print.default(x, args, missings))
}
<bytecode: 0x144d0c650>
<environment: namespace:base>

Other examples

mean
function (x, ...) 
UseMethod("mean")
<bytecode: 0x142928090>
<environment: namespace:base>
t.test
function (x, ...) 
UseMethod("t.test")
<bytecode: 0x153054fa0>
<environment: namespace:stats>
summary
function (object, ...) 
UseMethod("summary")
<bytecode: 0x1538264e8>
<environment: namespace:base>
plot
function (x, y, ...) 
UseMethod("plot")
<bytecode: 0x152a740a0>
<environment: namespace:base>

Not all base functions use this approach,

sum
function (..., na.rm = FALSE)  .Primitive("sum")

What is S3?


S3 is R’s first and simplest OO system. It is the only OO system used in the base and stats packages, and it’s the most commonly used system in CRAN packages. S3 is informal and ad hoc, but it has a certain elegance in its minimalism: you can’t take away any part of it and still have a useful OO system.

— Hadley Wickham, Advanced R

What’s going on?

S3 objects and their related functions work using a very simple dispatch mechanism - a generic function is created whose sole job is to call the UseMethod function which then calls a class specialized function using the naming convention: <generic>.<class>

We can see all of the specialized versions of the generic using the methods function.

methods("plot")
 [1] plot.acf*           plot.colors*        plot.data.frame*   
 [4] plot.decomposed.ts* plot.default        plot.dendrogram*   
 [7] plot.density*       plot.ecdf           plot.factor*       
[10] plot.formula*       plot.function       plot.hclust*       
[13] plot.histogram*     plot.HoltWinters*   plot.isoreg*       
[16] plot.lm*            plot.medpolish*     plot.mlm*          
[19] plot.ppr*           plot.prcomp*        plot.princomp*     
[22] plot.profile.nls*   plot.raster*        plot.spec*         
[25] plot.stepfun        plot.stl*           plot.table*        
[28] plot.ts             plot.tskernel*      plot.TukeyHSD*     
see '?methods' for accessing help and source code

Other examples

methods("print")
  [1] print.acf*                                          
  [2] print.activeConcordance*                            
  [3] print.AES*                                          
  [4] print.anova*                                        
  [5] print.aov*                                          
  [6] print.aovlist*                                      
  [7] print.ar*                                           
  [8] print.Arima*                                        
  [9] print.arima0*                                       
 [10] print.AsIs                                          
 [11] print.aspell*                                       
 [12] print.aspell_inspect_context*                       
 [13] print.bibentry*                                     
 [14] print.Bibtex*                                       
 [15] print.browseVignettes*                              
 [16] print.by                                            
 [17] print.changedFiles*                                 
 [18] print.check_bogus_return*                           
 [19] print.check_code_usage_in_package*                  
 [20] print.check_compiled_code*                          
 [21] print.check_demo_index*                             
 [22] print.check_depdef*                                 
 [23] print.check_details*                                
 [24] print.check_details_changes*                        
 [25] print.check_doi_db*                                 
 [26] print.check_dotInternal*                            
 [27] print.check_make_vars*                              
 [28] print.check_nonAPI_calls*                           
 [29] print.check_package_code_assign_to_globalenv*       
 [30] print.check_package_code_attach*                    
 [31] print.check_package_code_data_into_globalenv*       
 [32] print.check_package_code_startup_functions*         
 [33] print.check_package_code_syntax*                    
 [34] print.check_package_code_unload_functions*          
 [35] print.check_package_compact_datasets*               
 [36] print.check_package_CRAN_incoming*                  
 [37] print.check_package_datalist*                       
 [38] print.check_package_datasets*                       
 [39] print.check_package_depends*                        
 [40] print.check_package_description*                    
 [41] print.check_package_description_encoding*           
 [42] print.check_package_license*                        
 [43] print.check_packages_in_dir*                        
 [44] print.check_packages_used*                          
 [45] print.check_po_files*                               
 [46] print.check_pragmas*                                
 [47] print.check_Rd_line_widths*                         
 [48] print.check_Rd_metadata*                            
 [49] print.check_Rd_xrefs*                               
 [50] print.check_RegSym_calls*                           
 [51] print.check_S3_methods_needing_delayed_registration*
 [52] print.check_so_symbols*                             
 [53] print.check_T_and_F*                                
 [54] print.check_url_db*                                 
 [55] print.check_vignette_index*                         
 [56] print.checkDocFiles*                                
 [57] print.checkDocStyle*                                
 [58] print.checkFF*                                      
 [59] print.checkRd*                                      
 [60] print.checkRdContents*                              
 [61] print.checkReplaceFuns*                             
 [62] print.checkS3methods*                               
 [63] print.checkTnF*                                     
 [64] print.checkVignettes*                               
 [65] print.citation*                                     
 [66] print.cli_ansi_html_style*                          
 [67] print.cli_ansi_string*                              
 [68] print.cli_ansi_style*                               
 [69] print.cli_boxx*                                     
 [70] print.cli_diff_chr*                                 
 [71] print.cli_doc*                                      
 [72] print.cli_progress_demo*                            
 [73] print.cli_rule*                                     
 [74] print.cli_sitrep*                                   
 [75] print.cli_spark*                                    
 [76] print.cli_spinner*                                  
 [77] print.cli_tree*                                     
 [78] print.codoc*                                        
 [79] print.codocClasses*                                 
 [80] print.codocData*                                    
 [81] print.colorConverter*                               
 [82] print.colors*                                       
 [83] print.compactPDF*                                   
 [84] print.condition                                     
 [85] print.connection                                    
 [86] print.CRAN_package_reverse_dependencies_and_views*  
 [87] print.data.frame                                    
 [88] print.Date                                          
 [89] print.default                                       
 [90] print.dendrogram*                                   
 [91] print.density*                                      
 [92] print.difftime                                      
 [93] print.dist*                                         
 [94] print.Dlist                                         
 [95] print.DLLInfo                                       
 [96] print.DLLInfoList                                   
 [97] print.DLLRegisteredRoutines                         
 [98] print.document_context*                             
 [99] print.document_position*                            
[100] print.document_range*                               
[101] print.document_selection*                           
[102] print.dummy_coef*                                   
[103] print.dummy_coef_list*                              
[104] print.ecdf*                                         
[105] print.eigen                                         
[106] print.factanal*                                     
[107] print.factor                                        
[108] print.family*                                       
[109] print.fileSnapshot*                                 
[110] print.findLineNumResult*                            
[111] print.formula*                                      
[112] print.ftable*                                       
[113] print.function                                      
[114] print.getAnywhere*                                  
[115] print.glm*                                          
[116] print.hashtab*                                      
[117] print.hclust*                                       
[118] print.help_files_with_topic*                        
[119] print.hexmode                                       
[120] print.HoltWinters*                                  
[121] print.hsearch*                                      
[122] print.hsearch_db*                                   
[123] print.htest*                                        
[124] print.html*                                         
[125] print.html_dependency*                              
[126] print.htmltools.selector*                           
[127] print.htmltools.selector.list*                      
[128] print.infl*                                         
[129] print.integrate*                                    
[130] print.isoreg*                                       
[131] print.json*                                         
[132] print.key_missing*                                  
[133] print.kmeans*                                       
[134] print.knitr_kable*                                  
[135] print.Latex*                                        
[136] print.LaTeX*                                        
[137] print.libraryIQR                                    
[138] print.listof                                        
[139] print.lm*                                           
[140] print.loadings*                                     
[141] print.loess*                                        
[142] print.logLik*                                       
[143] print.ls_str*                                       
[144] print.medpolish*                                    
[145] print.MethodsFunction*                              
[146] print.mtable*                                       
[147] print.NativeRoutineList                             
[148] print.news_db*                                      
[149] print.nls*                                          
[150] print.noquote                                       
[151] print.numeric_version                               
[152] print.object_size*                                  
[153] print.octmode                                       
[154] print.packageDescription*                           
[155] print.packageInfo                                   
[156] print.packageIQR*                                   
[157] print.packageStatus*                                
[158] print.pairwise.htest*                               
[159] print.person*                                       
[160] print.POSIXct                                       
[161] print.POSIXlt                                       
[162] print.power.htest*                                  
[163] print.ppr*                                          
[164] print.prcomp*                                       
[165] print.princomp*                                     
[166] print.proc_time                                     
[167] print.quosure*                                      
[168] print.quosures*                                     
[169] print.raster*                                       
[170] print.Rconcordance*                                 
[171] print.Rd*                                           
[172] print.recordedplot*                                 
[173] print.restart                                       
[174] print.RGBcolorConverter*                            
[175] print.RGlyphFont*                                   
[176] print.rlang_box_done*                               
[177] print.rlang_box_splice*                             
[178] print.rlang_data_pronoun*                           
[179] print.rlang_dict*                                   
[180] print.rlang_dyn_array*                              
[181] print.rlang_envs*                                   
[182] print.rlang_error*                                  
[183] print.rlang_fake_data_pronoun*                      
[184] print.rlang_lambda_function*                        
[185] print.rlang_message*                                
[186] print.rlang_trace*                                  
[187] print.rlang_warning*                                
[188] print.rlang_zap*                                    
[189] print.rlang:::list_of_conditions*                   
[190] print.rle                                           
[191] print.rlib_bytes*                                   
[192] print.rlib_error_3_0*                               
[193] print.rlib_trace_3_0*                               
[194] print.roman*                                        
[195] print.scalar*                                       
[196] print.sessionInfo*                                  
[197] print.shiny.tag*                                    
[198] print.shiny.tag.env*                                
[199] print.shiny.tag.list*                               
[200] print.shiny.tag.query*                              
[201] print.simple.list                                   
[202] print.smooth.spline*                                
[203] print.socket*                                       
[204] print.srcfile                                       
[205] print.srcref                                        
[206] print.stepfun*                                      
[207] print.stl*                                          
[208] print.StructTS*                                     
[209] print.subdir_tests*                                 
[210] print.summarize_CRAN_check_status*                  
[211] print.summary.aov*                                  
[212] print.summary.aovlist*                              
[213] print.summary.ecdf*                                 
[214] print.summary.glm*                                  
[215] print.summary.lm*                                   
[216] print.summary.loess*                                
[217] print.summary.manova*                               
[218] print.summary.nls*                                  
[219] print.summary.packageStatus*                        
[220] print.summary.ppr*                                  
[221] print.summary.prcomp*                               
[222] print.summary.princomp*                             
[223] print.summary.table                                 
[224] print.summary.warnings                              
[225] print.summaryDefault                                
[226] print.table                                         
[227] print.tables_aov*                                   
[228] print.terms*                                        
[229] print.ts*                                           
[230] print.tskernel*                                     
[231] print.TukeyHSD*                                     
[232] print.tukeyline*                                    
[233] print.tukeysmooth*                                  
[234] print.undoc*                                        
[235] print.vignette*                                     
[236] print.warnings                                      
[237] print.xfun_raw_string*                              
[238] print.xfun_rename_seq*                              
[239] print.xfun_strict_list*                             
[240] print.xgettext*                                     
[241] print.xngettext*                                    
[242] print.xtabs*                                        
see '?methods' for accessing help and source code
print.factor
function (x, quote = FALSE, max.levels = NULL, width = getOption("width"), 
    ...) 
{
    ord <- is.ordered(x)
    if (length(x) == 0L) 
        cat(if (ord) 
            "ordered"
        else "factor", "()\n", sep = "")
    else {
        xx <- character(length(x))
        xx[] <- as.character(x)
        keepAttrs <- setdiff(names(attributes(x)), c("levels", 
            "class"))
        attributes(xx)[keepAttrs] <- attributes(x)[keepAttrs]
        print(xx, quote = quote, ...)
    }
    maxl <- if (is.null(max.levels)) 
        TRUE
    else max.levels
    if (maxl) {
        n <- length(lev <- encodeString(levels(x), quote = ifelse(quote, 
            "\"", "")))
        colsep <- if (ord) 
            " < "
        else " "
        T0 <- "Levels: "
        if (is.logical(maxl)) 
            maxl <- {
                width <- width - (nchar(T0, "w") + 3L + 1L + 
                  3L)
                lenl <- cumsum(nchar(lev, "w") + nchar(colsep, 
                  "w"))
                if (n <= 1L || lenl[n] <= width) 
                  n
                else max(1L, which.max(lenl > width) - 1L)
            }
        drop <- n > maxl
        cat(if (drop) 
            paste(format(n), ""), T0, paste(if (drop) 
            c(lev[1L:max(1, maxl - 1)], "...", if (maxl > 1) lev[n])
        else lev, collapse = colsep), "\n", sep = "")
    }
    if (!isTRUE(val <- .valid.factor(x))) 
        warning(val)
    invisible(x)
}
<bytecode: 0x142f79320>
<environment: namespace:base>

The other way

If instead we have a class and want to know what specialized functions exist for that class, then we can again use the methods function with the class argument.

methods(class="factor")
 [1] [             [[            [[<-          [<-           all.equal    
 [6] as.character  as.data.frame as.Date       as.list       as.logical   
[11] as.POSIXlt    as.vector     c             coerce        droplevels   
[16] format        initialize    is.na<-       length<-      levels<-     
[21] Math          Ops           plot          print         relevel      
[26] relist        rep           show          slotsFromS3   summary      
[31] Summary       xtfrm        
see '?methods' for accessing help and source code

Adding methods

x = structure(c(1,2,3), 
              class="class_A")
x
[1] 1 2 3
attr(,"class")
[1] "class_A"
y = structure(c(6,5,4), 
              class="class_B")
y
[1] 6 5 4
attr(,"class")
[1] "class_B"
print.class_A = function(x) {
  cat("Class A!\n")
  print.default(unclass(x))
}
x
Class A!
[1] 1 2 3
print.class_B = function(x) {
  cat("Class B!\n")
  print.default(unclass(x))
}
y
Class B!
[1] 6 5 4
class(x) = "class_B"
x
Class B!
[1] 1 2 3
class(y) = "class_A"
y
Class A!
[1] 6 5 4

Defining a new S3 Generic

shuffle = function(x) {
  UseMethod("shuffle")
}
shuffle.default = function(x) {
  stop("Class ", class(x), " is not supported by shuffle.\n", call. = FALSE)
}
shuffle.factor = function(f) {
  factor( sample(as.character(f)), levels = sample(levels(f)) )
}
shuffle.integer = function(x) {
  sample(x)
}

Shuffle results

shuffle( 1:10 )
 [1]  6  9  8 10  3  5  4  7  1  2
shuffle( factor(c("A","B","C","A")) )
[1] A A C B
Levels: C B A
shuffle( c(1, 2, 3, 4, 5) )
Error: Class numeric is not supported by shuffle.
shuffle( letters[1:5] )
Error: Class character is not supported by shuffle.

Exercise 2 - classes, modes, and types

Below we have defined an S3 method called report, it is designed to return a message about the type/mode/class of an object passed to it.

report = function(x) {
  UseMethod("report")
}

report.default = function(x) {
  "This class does not have a method defined."
}
report.integer = function(x) {
 "I'm an integer!"
}

report.double = function(x) {
  "I'm a double!"
}

report.numeric = function(x) {
  "I'm a numeric!"
}
  • Try running the report function with different input types, what happens?

  • Now run rm("report.integer") in your Console and try using the report function again, what has changed?

  • What does this tell us about S3, types, modes, and classes?

  • What if we also rm("report.double")?

Conclusions?

From UseMethods R documentation:

If the object does not have a class attribute, it has an implicit class. Matrices and arrays have class “matrix” or “array” followed by the class of the underlying vector. Most vectors have class the result of mode(x), except that integer vectors have class c("integer", "numeric") and real vectors have class c("double", "numeric").

From Advanced R:

How does UseMethod() work? It basically creates a vector of method names, paste0(“generic”, “.”, c(class(x), “default”)), and then looks for each potential method in turn.

Why?

See @WhyDoesR