library(tidyverse) # stringr package is part of the tidyverse collection.Illustrate S3 System – U of I Women’s Basketball Team example
- Make sure to read the following section before referring to this lab help document.
- In the R ecosystem, S3 is the most popular object-oriented programming (OOP) system.
- The main components of S3: classes, generics, and methods
- Generics, methods, and dispatch

- To create a new S3 class, three functions are used in most classes:
- constructor – Create a raw S3 object (
new_myclass()) - validator – Ensure the values are valid (
validate_myclass()) - helper – A user-friendly function that combines both (
myclass())
- constructor – Create a raw S3 object (
U of I Women’s Basketball Team
Introducing our amazing women’s basketball team! Find more information about the team on this page.
https://fightingillini.com/sports/womens-basketball/roster
Objective: Display the profile information according to roles
- For player, print the profile information like
- Adalia Mckenzie is a player on the U of I Women’s Basketball Team. Her jersey number is 24. Adalia is a student in her Senior year. She is 5-10 tall (177.8 cm). Her position is Guard.
- For staff, print the profile information like
- Shauna Green is the Head Coach of the U of I Women’s Basketball Team.
- Maya Solomon is a staff member of the U of I Women’s Basketball Team.
- For all other people, like the spectator, print the information like
- Weijia Jia is neither a player nor a staff member.
Create Player Class
Constructor Function for Player Class
new_player <- function(firstname, lastname, jersey, position,
studentclass, height_inches, height_cm) {
stopifnot(is.character(firstname))
stopifnot(is.character(lastname))
structure(
list(
firstname = firstname,
lastname = lastname,
jersey = jersey,
position = position,
studentclass = studentclass,
height_inches = height_inches,
height_cm = height_cm
),
class = "player"
)
}Validator Function for Player Class
- If any information is missing, print ‘… is missing’.
- If the pattern of height doesn’t follow the “feet-inches” pattern, print a warning message.
- If the position is not one of the three categories (Guard, Forward, Center), print a warning message.
- If the class is not one of the five categories (Freshman, Sophomore, Junior, Senior, Fifth), print a warning message.
validate_player <- function(x){
if(is.na(x$firstname)) print("The player's first name is missing.")
if(is.na(x$lastname)) print("The player's last name is missing.")
if(is.na(x$jersey)) print("The player's jersey information is missing.")
if(is.na(x$position)) print("The player's position information is missing.")
if(is.na(x$studentclass)) print("The player's class information is missing.")
if(is.na(x$height_inches)) print("The player's height information in inches is missing.")
if(!str_to_title(x$position) %in% c("Guard", "Forward", "Center"))
print("The player's position information is invalid.")
if(!str_to_title(x$studentclass) %in% c("Freshman", "Sophomore", "Junior", "Senior", "Fifth"))
print("The player's class information is invalid.")
if(!grepl("^\\d+-\\d+$", x$height_inches)) # grepl() is searching for matches
print("The player's height does not follow the 'feet-inches' pattern.")
x
}Helper Function for Player Class
First, define a function convertHeightToCm() to convert the height from the “feet-inches” pattern to centimeters.
- Define the function
convertHeightToCm()
convertHeightToCm <- function(height) {
# Split the input string by the dash
parts <- str_split(height, "-")[[1]] # str_split() is from stringr package
# Extract feet and inches as numeric values
feet <- as.numeric(parts[1])
inches <- as.numeric(parts[2])
# Convert feet to inches and then total inches to centimeters
height_inches <- (feet * 12) + inches
height_cm <- height_inches * 2.54
return(height_cm)
}- Define the Helper Function
player <- function(firstname, lastname, jersey, position,
studentclass, height) {
firstname = str_to_title(firstname) # str_to_title() is from stringr
lastname = str_to_title(lastname)
jersey = as.character(jersey)
position = str_to_title(position)
studentclass = str_to_title(studentclass)
height_inches = height
height_cm = convertHeightToCm(height)
validate_player(new_player(firstname, lastname, jersey, position,
studentclass, height_inches, height_cm))
}Create Staff Class
Constructor Function for Staff Class
new_staff = function(name, role, role_with_article = NULL){
stopifnot(is.character(name))
stopifnot(is.character(role))
structure(
list(name = name,
role = role,
role_with_article = role_with_article
),
class = "staff"
)
}Validator Function for Staff Class
- if name or role is missing or not character type, print warning message.
validate_staff <- function(x){
if(is.na(x$name) || !is.character(x$name))
print("The staff's name is not valid")
if(is.na(x$role)|| !is.character(x$role))
print("The staff's role information is not valid")
x
}Helper Function for Staff Class
First, define a function article_selector() to help choosing appropriate article for the role information.
article_selector <- function(role) {
title <- switch(
role,
"head coach" = "the Head Coach",
"associate head coach" = "the Associate Head Coach",
"assistant coach" = "an Assistant Coach",
"a staff member"
)
return(title)
}The helper function for staff
staff <- function(name, role){
name = str_to_title(name)
role = role
role_with_article = article_selector(role)
validate_staff(new_staff(name, role, role_with_article))
}Create Spectator Class
new_spectator = function(name){
structure(
list(name = name),
class = "other"
)
}Generic and Methods
- Define the generic function
Typically, we define a generic function by writing code that includes a call to UseMethod().
my_generic <- function(x, ...) {
UseMethod("my_generic")
}But in this case, print() is a defined generic existing in R already. We can directly use it and go ahead to define methods for the custom class.
- Define the methods
print.player = function(x){
cat(paste0(
x$firstname, " ",
x$lastname, " is a player on the U of I Women's Basketball Team. ",
"Her jersey number is ", x$jersey, ". ",
x$firstname, " is a student in her ", x$studentclass, " year. ",
"She is ", x$height_inches, " tall (", x$height_cm," cm). ",
"Her position is ", x$position, "."
)
)
}
print.staff = function(x){
cat(paste0(x$name, " is ", x$role_with_article,
" of the U of I Women's Basketball Team." ))
}
print.other = function(x){
cat(paste0(x$name, " is neither a player nor a staff member."))
}Test
Define Objects
# Player
Mckenzie <- player(
firstname = "Adalia",
lastname = "Mckenzie",
jersey = "24",
position = "guard",
studentclass = "senior",
height = "5-10"
)
### Incorrect Usage
Bryant <- player(
firstname = "Genesis",
lastname = "Bryant",
jersey = "1",
position = "guard",
studentclass = "fifth",
height = "5'6''"
)
#> Warning in convertHeightToCm(height): NAs introduced by coercion
#> [1] "The player's height does not follow the 'feet-inches' pattern."
# Corrected
Bryant <- player(
firstname = "Genesis",
lastname = "Bryant",
jersey = "1",
position = "guard",
studentclass = "fifth",
height = "5-6")
# Staff
Green <- staff(
name = "shauna green",
role = "head coach"
)
Solomon <- staff(
name = "Maya Solomon",
role = "director of basketball operations"
)
# Spectator
Jia <- new_spectator(
name = "Weijia Jia"
)Display Information
print(Mckenzie)
#> Adalia Mckenzie is a player on the U of I Women's Basketball Team. Her jersey number is 24. Adalia is a student in her Senior year. She is 5-10 tall (177.8 cm). Her position is Guard.
print(Bryant)
#> Genesis Bryant is a player on the U of I Women's Basketball Team. Her jersey number is 1. Genesis is a student in her Fifth year. She is 5-6 tall (167.64 cm). Her position is Guard.
print(Green)
#> Shauna Green is the Head Coach of the U of I Women's Basketball Team.
print(Solomon)
#> Maya Solomon is a staff member of the U of I Women's Basketball Team.
print(Jia)
#> Weijia Jia is neither a player nor a staff member.Mckenzie
#> Adalia Mckenzie is a player on the U of I Women's Basketball Team. Her jersey number is 24. Adalia is a student in her Senior year. She is 5-10 tall (177.8 cm). Her position is Guard.
Bryant
#> Genesis Bryant is a player on the U of I Women's Basketball Team. Her jersey number is 1. Genesis is a student in her Fifth year. She is 5-6 tall (167.64 cm). Her position is Guard.
Green
#> Shauna Green is the Head Coach of the U of I Women's Basketball Team.
Solomon
#> Maya Solomon is a staff member of the U of I Women's Basketball Team.
Jia
#> Weijia Jia is neither a player nor a staff member.