Using Inheritance in S3
Inheritance in S3 allows you to create a hierarchy of classes where a class can inherit properties and methods from another class. This enables you to build complex object-oriented systems with reusable and extendable components.
Basic Concept of Inheritance in S3
In S3, inheritance is managed by assigning multiple classes to an object. Methods are chosen based on the first class in the object’s class attribute. This means you can create subclasses that extend the functionality of base classes.
Example of Class Hierarchy
Let’s consider an example where we have a base class Person and a subclass Student that inherits from Person.
Creating the Base Class Person
Define a Constructor for Person:
# Define a constructor for the Person class create_person <- function(name, age) { # Create a list with attributes obj <- list(name = name, age = age) # Set the class attribute class(obj) <- "Person" return(obj) } # Create an instance of the Person class alice <- create_person("Alice", 30)
Define a Method for Person:
# Define a print method for the Person class print.Person <- function(x) { cat("Name:", x$name, "\nAge:", x$age, "\n") } # Use the print method print(alice) # Calls print.Person
Creating the Subclass Student
Define a Constructor for Student:
# Define a constructor for the Student class create_student <- function(name, age, student_id) { # Create a Person object and add an additional attribute obj <- create_person(name, age) obj$student_id <- student_id class(obj) <- c("Student", "Person") # Specify the class order return(obj) } # Create an instance of the Student class charlie <- create_student("Charlie", 22, "S123")
Define a Method for Student:
# Define a print method for the Student class print.Student <- function(x) { # Call the print method for Person print.Person(x) cat("Student ID:", x$student_id, "\n") } # Use the print method for Student print(charlie) # Calls print.Student
Method Dispatch Based on Inheritance
When an object belongs to multiple classes, R chooses the method to call based on the first class listed in the class attribute.
Example of Method Dispatch with Inheritance
Define a Method for Another Class:
# Define a print method for another class Animal print.Animal <- function(x) { cat("Animal Name:", x$name, "\n") } # Create an Animal object lion <- structure(list(name = "Lion"), class = "Animal") # Create an object with both Animal and Person classes combined <- structure(list(name = "Tiger", age = 5), class = c("Person", "Animal")) # Use print on the objects print(lion) # Calls print.Animal print(combined) # Calls print.Person (since Person is the first class)
Complete Example with Complex Inheritance
Let’s model a hierarchy of geometric shapes.
Define a Base Class Shape:
# Define a constructor for the Shape class create_shape <- function(color) { obj <- list(color = color) class(obj) <- "Shape" return(obj) } # Define a print method for Shape print.Shape <- function(x) { cat("Color:", x$color, "\n") }
Create Subclasses Circle and Rectangle:
# Define a constructor for Circle create_circle <- function(color, radius) { obj <- create_shape(color) obj$radius <- radius class(obj) <- c("Circle", "Shape") return(obj) } # Define a constructor for Rectangle create_rectangle <- function(color, width, height) { obj <- create_shape(color) obj$width <- width obj$height <- height class(obj) <- c("Rectangle", "Shape") return(obj) } # Define a print method for Circle print.Circle <- function(x) { print.Shape(x) cat("Radius:", x$radius, "\n") } # Define a print method for Rectangle print.Rectangle <- function(x) { print.Shape(x) cat("Width:", x$width, "\nHeight:", x$height, "\n") } # Create instances circle <- create_circle("Red", 5) rectangle <- create_rectangle("Blue", 4, 6) # Use print print(circle) # Calls print.Circle print(rectangle) # Calls print.Rectangle
Key Points of S3 Inheritance
- Order of Classes: When an object has multiple classes, the method is called based on the first class in the list.
- Flexibility: Objects can belong to multiple classes, allowing for the definition of methods specific to each class.
- Simplicity: S3 inheritance is straightforward to implement and uses class attributes and list management.
Conclusion
Inheritance in S3 allows you to build class hierarchies where a class can extend the functionality of another class. By defining constructors, methods, and managing the order of classes, you can create complex object-oriented systems in R that are flexible and reusable.