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
<- function(firstname, lastname, jersey, position,
new_player
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.
<- function(x){
validate_player 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()
<- function(height) {
convertHeightToCm # Split the input string by the dash
<- str_split(height, "-")[[1]] # str_split() is from stringr package
parts
# Extract feet and inches as numeric values
<- as.numeric(parts[1])
feet <- as.numeric(parts[2])
inches
# Convert feet to inches and then total inches to centimeters
<- (feet * 12) + inches
height_inches <- height_inches * 2.54
height_cm
return(height_cm)
}
- Define the Helper Function
<- function(firstname, lastname, jersey, position,
player
studentclass, height) {= str_to_title(firstname) # str_to_title() is from stringr
firstname = str_to_title(lastname)
lastname = as.character(jersey)
jersey = str_to_title(position)
position = str_to_title(studentclass)
studentclass = height
height_inches = convertHeightToCm(height)
height_cm
validate_player(new_player(firstname, lastname, jersey, position,
studentclass, height_inches, height_cm)) }
Create Staff Class
Constructor Function for Staff Class
= function(name, role, role_with_article = NULL){
new_staff 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.
<- function(x){
validate_staff 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.
<- function(role) {
article_selector <- switch(
title
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
<- function(name, role){
staff = str_to_title(name)
name = role
role = article_selector(role)
role_with_article
validate_staff(new_staff(name, role, role_with_article))
}
Create Spectator Class
= function(name){
new_spectator 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()
.
<- function(x, ...) {
my_generic 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
= function(x){
print.player cat(paste0(
$firstname, " ",
x$lastname, " is a player on the U of I Women's Basketball Team. ",
x"Her jersey number is ", x$jersey, ". ",
$firstname, " is a student in her ", x$studentclass, " year. ",
x"She is ", x$height_inches, " tall (", x$height_cm," cm). ",
"Her position is ", x$position, "."
)
)
}
= function(x){
print.staff cat(paste0(x$name, " is ", x$role_with_article,
" of the U of I Women's Basketball Team." ))
}
= function(x){
print.other cat(paste0(x$name, " is neither a player nor a staff member."))
}
Test
Define Objects
# Player
<- player(
Mckenzie firstname = "Adalia",
lastname = "Mckenzie",
jersey = "24",
position = "guard",
studentclass = "senior",
height = "5-10"
)
### Incorrect Usage
<- player(
Bryant 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
<- player(
Bryant firstname = "Genesis",
lastname = "Bryant",
jersey = "1",
position = "guard",
studentclass = "fifth",
height = "5-6")
# Staff
<- staff(
Green name = "shauna green",
role = "head coach"
)
<- staff(
Solomon name = "Maya Solomon",
role = "director of basketball operations"
)
# Spectator
<- new_spectator(
Jia 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.