R
Tutorial R: Herencia y polimorfismo en R
Aprende herencia, polimorfismo y composición en R con ejemplos en S3, S4 y R6 para programación orientada a objetos avanzada.
Aprende R y certifícateHerencia en S3, S4 y R6
La herencia es uno de los pilares fundamentales de la programación orientada a objetos que permite crear nuevas clases basadas en clases existentes. En R, este concepto se implementa de manera diferente según el sistema de orientación a objetos que utilicemos: S3, S4 o R6. Cada uno ofrece distintos niveles de formalidad y flexibilidad.
Herencia en el sistema S3
El sistema S3 implementa la herencia de forma muy sencilla y flexible, aunque menos formal que otros sistemas. En S3, la herencia se logra simplemente añadiendo múltiples clases a un objeto.
Para crear una clase derivada en S3, utilizamos el atributo class
:
# Creamos una clase base "vehículo"
crear_vehiculo <- function(tipo, velocidad_max) {
vehiculo <- list(tipo = tipo, velocidad_max = velocidad_max)
class(vehiculo) <- "vehiculo"
return(vehiculo)
}
# Método para la clase base
print.vehiculo <- function(x, ...) {
cat("Vehículo:", x$tipo, "\n")
cat("Velocidad máxima:", x$velocidad_max, "km/h\n")
}
# Creamos una subclase "coche" que hereda de "vehículo"
crear_coche <- function(modelo, velocidad_max) {
coche <- crear_vehiculo("coche", velocidad_max)
coche$modelo <- modelo
# Asignamos múltiples clases - la herencia en S3
class(coche) <- c("coche", "vehiculo")
return(coche)
}
# Método específico para la subclase
print.coche <- function(x, ...) {
cat("Coche modelo:", x$modelo, "\n")
cat("Velocidad máxima:", x$velocidad_max, "km/h\n")
}
Veamos cómo funciona:
# Creamos instancias
mi_vehiculo <- crear_vehiculo("genérico", 120)
mi_coche <- crear_coche("Sedan", 180)
# Probamos los métodos
print(mi_vehiculo)
print(mi_coche)
En S3, cuando llamamos a un método como print()
, R busca primero un método específico para la primera clase del objeto (print.coche
). Si no lo encuentra, continúa con la siguiente clase en la lista (print.vehiculo
). Esta es la forma en que S3 implementa la búsqueda de métodos en la jerarquía de herencia.
Herencia en el sistema S4
El sistema S4 ofrece una implementación más formal y estructurada de la herencia. Aquí, las relaciones de herencia se definen explícitamente al crear las clases.
# Cargamos la biblioteca necesaria
library(methods)
# Definimos la clase base
setClass("Vehiculo",
slots = list(
tipo = "character",
velocidad_max = "numeric"
))
# Definimos un método para la clase base
setMethod("show", "Vehiculo",
function(object) {
cat("Vehículo:", object@tipo, "\n")
cat("Velocidad máxima:", object@velocidad_max, "km/h\n")
})
# Definimos una subclase que hereda de Vehiculo
setClass("Coche",
slots = list(
modelo = "character"
),
contains = "Vehiculo") # Aquí especificamos la herencia
# Definimos un método específico para la subclase
setMethod("show", "Coche",
function(object) {
cat("Coche modelo:", object@modelo, "\n")
cat("Velocidad máxima:", object@velocidad_max, "km/h\n")
})
Probemos nuestras clases S4:
# Creamos instancias
mi_vehiculo_s4 <- new("Vehiculo", tipo = "genérico", velocidad_max = 120)
mi_coche_s4 <- new("Coche", tipo = "coche", velocidad_max = 180, modelo = "Sedan")
# Mostramos los objetos
show(mi_vehiculo_s4)
show(mi_coche_s4)
En S4, la herencia se especifica mediante el parámetro contains
al definir una clase. La clase Coche
hereda todos los slots (atributos) de Vehiculo
y puede añadir sus propios slots adicionales.
Herencia en el sistema R6
R6 es un sistema de clases más moderno que implementa programación orientada a objetos al estilo de otros lenguajes como Python o Java. La herencia en R6 es más intuitiva para quienes vienen de otros lenguajes de programación.
# Cargamos la biblioteca R6
library(R6)
# Definimos la clase base
Vehiculo <- R6Class("Vehiculo",
public = list(
tipo = NULL,
velocidad_max = NULL,
initialize = function(tipo, velocidad_max) {
self$tipo <- tipo
self$velocidad_max <- velocidad_max
},
imprimir = function() {
cat("Vehículo:", self$tipo, "\n")
cat("Velocidad máxima:", self$velocidad_max, "km/h\n")
}
)
)
# Definimos una subclase que hereda de Vehiculo
Coche <- R6Class("Coche",
inherit = Vehiculo, # Aquí especificamos la herencia
public = list(
modelo = NULL,
initialize = function(modelo, velocidad_max) {
super$initialize("coche", velocidad_max) # Llamamos al constructor de la clase padre
self$modelo <- modelo
},
imprimir = function() {
cat("Coche modelo:", self$modelo, "\n")
cat("Velocidad máxima:", self$velocidad_max, "km/h\n")
}
)
)
Veamos cómo funciona:
# Creamos instancias
mi_vehiculo_r6 <- Vehiculo$new("genérico", 120)
mi_coche_r6 <- Coche$new("Sedan", 180)
# Llamamos a los métodos
mi_vehiculo_r6$imprimir()
mi_coche_r6$imprimir()
En R6, la herencia se especifica mediante el parámetro inherit
. La clase derivada puede acceder a los métodos y propiedades de la clase base usando super$
. Esto permite una sobrescritura controlada de métodos, donde podemos decidir si queremos reemplazar completamente un método o extender su funcionalidad.
Comparación de los tres sistemas
- S3: Ofrece herencia simple mediante listas de clases. Es flexible pero menos formal.
- S4: Proporciona herencia explícita con validación de tipos. Es más estructurado y robusto.
- R6: Implementa herencia al estilo de otros lenguajes OOP modernos. Es intuitivo y permite encapsulamiento.
Cada sistema tiene sus ventajas según el contexto:
- Usa S3 para soluciones rápidas y flexibles cuando la estructura formal no es crítica.
- Elige S4 cuando necesites un sistema robusto con validación de tipos y una estructura clara.
- Opta por R6 cuando prefieras una sintaxis similar a otros lenguajes OOP y necesites encapsulamiento verdadero.
La elección del sistema dependerá de la complejidad de tu proyecto y de tus preferencias personales. Para proyectos pequeños, S3 puede ser suficiente, mientras que para aplicaciones más grandes y complejas, S4 o R6 ofrecen mayor robustez y claridad estructural.
Polimorfismo y dispatch de métodos
El polimorfismo es uno de los conceptos fundamentales de la programación orientada a objetos que permite que objetos de diferentes clases respondan al mismo mensaje o método de maneras distintas. En R, este concepto se implementa principalmente a través del mecanismo de dispatch de métodos, que determina qué implementación de un método debe ejecutarse según el tipo de objeto.
Polimorfismo en el sistema S3
En S3, el polimorfismo se implementa mediante funciones genéricas que seleccionan el método apropiado basándose en la clase del objeto. Este proceso se conoce como dispatch simple porque solo considera la clase del primer argumento.
# Creamos dos clases diferentes
crear_rectangulo <- function(ancho, alto) {
obj <- list(ancho = ancho, alto = alto)
class(obj) <- "rectangulo"
return(obj)
}
crear_circulo <- function(radio) {
obj <- list(radio = radio)
class(obj) <- "circulo"
return(obj)
}
# Definimos una función genérica
calcular_area <- function(figura) {
UseMethod("calcular_area") # Esto activa el dispatch de métodos
}
# Implementamos métodos específicos para cada clase
calcular_area.rectangulo <- function(figura) {
return(figura$ancho * figura$alto)
}
calcular_area.circulo <- function(figura) {
return(pi * figura$radio^2)
}
# Método por defecto (se usa cuando no hay método específico)
calcular_area.default <- function(figura) {
warning("No se puede calcular el área para este tipo de objeto")
return(NA)
}
Veamos cómo funciona el polimorfismo:
# Creamos instancias
mi_rectangulo <- crear_rectangulo(5, 3)
mi_circulo <- crear_circulo(2)
# La misma función se comporta diferente según el tipo de objeto
calcular_area(mi_rectangulo) # Devuelve 15
calcular_area(mi_circulo) # Devuelve 12.56637...
calcular_area("texto") # Activa el método default y devuelve NA
El dispatch de métodos en S3 funciona así:
- Cuando llamamos a
calcular_area(mi_rectangulo)
, R busca una función llamadacalcular_area.rectangulo
- Si no la encuentra, busca métodos para las clases padre (si existen)
- Si no encuentra ningún método aplicable, usa
calcular_area.default
Polimorfismo en el sistema S4
S4 ofrece un sistema de dispatch más sofisticado que puede considerar múltiples argumentos, conocido como dispatch múltiple. Esto permite seleccionar métodos basados en la combinación de clases de varios argumentos.
library(methods)
# Definimos clases S4
setClass("Figura")
setClass("Rectangulo",
slots = c(ancho = "numeric", alto = "numeric"),
contains = "Figura")
setClass("Circulo",
slots = c(radio = "numeric"),
contains = "Figura")
# Definimos una función genérica
setGeneric("calcularArea", function(figura) {
standardGeneric("calcularArea")
})
# Implementamos métodos para cada clase
setMethod("calcularArea", "Rectangulo", function(figura) {
return(figura@ancho * figura@alto)
})
setMethod("calcularArea", "Circulo", function(figura) {
return(pi * figura@radio^2)
})
# Método para la clase base (opcional)
setMethod("calcularArea", "Figura", function(figura) {
warning("No se puede calcular el área para esta figura genérica")
return(NA)
})
Probemos el polimorfismo en S4:
# Creamos instancias
mi_rectangulo_s4 <- new("Rectangulo", ancho = 5, alto = 3)
mi_circulo_s4 <- new("Circulo", radio = 2)
# La misma función se comporta diferente según el tipo de objeto
calcularArea(mi_rectangulo_s4) # Devuelve 15
calcularArea(mi_circulo_s4) # Devuelve 12.56637...
El dispatch múltiple en S4 permite definir métodos basados en múltiples argumentos:
# Definimos una función genérica con dos argumentos
setGeneric("solapan", function(figura1, figura2) {
standardGeneric("solapan")
})
# Implementamos métodos para diferentes combinaciones de clases
setMethod("solapan",
signature(figura1 = "Rectangulo", figura2 = "Rectangulo"),
function(figura1, figura2) {
# Lógica para comprobar si dos rectángulos se solapan
return(TRUE) # Simplificado para el ejemplo
})
setMethod("solapan",
signature(figura1 = "Circulo", figura2 = "Circulo"),
function(figura1, figura2) {
# Lógica para comprobar si dos círculos se solapan
return(FALSE) # Simplificado para el ejemplo
})
setMethod("solapan",
signature(figura1 = "Rectangulo", figura2 = "Circulo"),
function(figura1, figura2) {
# Lógica para comprobar si un rectángulo y un círculo se solapan
return(TRUE) # Simplificado para el ejemplo
})
# El método se selecciona basándose en ambos argumentos
solapan(mi_rectangulo_s4, mi_circulo_s4) # Usa el método Rectangulo-Circulo
Polimorfismo en el sistema R6
En R6, el polimorfismo se implementa principalmente a través de la sobrescritura de métodos en las clases derivadas. A diferencia de S3 y S4, R6 no utiliza un mecanismo de dispatch centralizado, sino que se basa en la jerarquía de clases y el acceso a métodos a través de la referencia self
.
library(R6)
# Definimos una clase base
Figura <- R6Class("Figura",
public = list(
calcular_area = function() {
stop("Método abstracto: debe ser implementado por las subclases")
},
describir = function() {
cat("Esta es una figura geométrica\n")
}
)
)
# Definimos subclases
Rectangulo <- R6Class("Rectangulo",
inherit = Figura,
public = list(
ancho = NULL,
alto = NULL,
initialize = function(ancho, alto) {
self$ancho <- ancho
self$alto <- alto
},
calcular_area = function() {
return(self$ancho * self$alto)
},
describir = function() {
super$describir() # Llamamos al método de la clase base
cat("Específicamente, soy un rectángulo\n")
}
)
)
Circulo <- R6Class("Circulo",
inherit = Figura,
public = list(
radio = NULL,
initialize = function(radio) {
self$radio <- radio
},
calcular_area = function() {
return(pi * self$radio^2)
},
describir = function() {
super$describir() # Llamamos al método de la clase base
cat("Específicamente, soy un círculo\n")
}
)
)
Veamos cómo funciona el polimorfismo en R6:
# Creamos instancias
mi_rectangulo_r6 <- Rectangulo$new(5, 3)
mi_circulo_r6 <- Circulo$new(2)
# Cada objeto responde al mismo método de manera diferente
mi_rectangulo_r6$calcular_area() # Devuelve 15
mi_circulo_r6$calcular_area() # Devuelve 12.56637...
# Ambos objetos extienden el comportamiento del método describir
mi_rectangulo_r6$describir()
mi_circulo_r6$describir()
Dispatch dinámico vs. estático
R implementa principalmente dispatch dinámico, lo que significa que la selección del método ocurre en tiempo de ejecución, no durante la compilación. Esto ofrece mayor flexibilidad pero puede ser menos eficiente que el dispatch estático.
# Ejemplo de dispatch dinámico en S3
objeto <- if(runif(1) > 0.5) {
crear_rectangulo(4, 3)
} else {
crear_circulo(2)
}
# El método correcto se selecciona en tiempo de ejecución
calcular_area(objeto) # Llamará al método apropiado según el resultado aleatorio
Comparación de dispatch entre sistemas
- S3: Dispatch simple basado en la clase del primer argumento. Es flexible pero menos formal.
- S4: Dispatch múltiple basado en las clases de varios argumentos. Es más potente y estructurado.
- R6: No tiene un mecanismo de dispatch centralizado; se basa en la jerarquía de clases y el acceso a métodos a través de
self
ysuper
.
Aplicación práctica del polimorfismo
El polimorfismo es especialmente útil cuando trabajamos con colecciones heterogéneas de objetos:
# Creamos una lista de figuras de diferentes tipos
figuras <- list(
crear_rectangulo(5, 3),
crear_circulo(2),
crear_rectangulo(2, 2),
crear_circulo(3)
)
# Calculamos el área de todas las figuras con una sola función
areas <- sapply(figuras, calcular_area)
print(areas)
# Podemos procesar objetos de diferentes tipos de manera uniforme
total_area <- sum(areas)
cat("Área total:", total_area, "\n")
El polimorfismo nos permite escribir código más genérico y reutilizable, ya que podemos trabajar con objetos de diferentes tipos a través de una interfaz común. Esto facilita la extensión del código, pues podemos añadir nuevos tipos de objetos sin modificar el código existente, siempre que implementen los métodos esperados.
Composición como alternativa a la herencia
La composición es un patrón de diseño que ofrece una alternativa flexible a la herencia para reutilizar código y construir relaciones entre objetos. En lugar de establecer relaciones "es un" (como hace la herencia), la composición establece relaciones "tiene un", donde un objeto contiene instancias de otros objetos como sus componentes.
En R, podemos implementar la composición en los tres sistemas de programación orientada a objetos (S3, S4 y R6), cada uno con sus particularidades.
Composición en el sistema S3
En S3, la composición se implementa simplemente incluyendo objetos dentro de otros como elementos de una lista:
# Creamos una clase "motor"
crear_motor <- function(potencia, tipo) {
motor <- list(potencia = potencia, tipo = tipo)
class(motor) <- "motor"
return(motor)
}
print.motor <- function(x, ...) {
cat("Motor", x$tipo, "de", x$potencia, "CV\n")
}
# Creamos una clase "coche" que CONTIENE un motor (composición)
crear_coche_compuesto <- function(modelo, motor) {
coche <- list(modelo = modelo, motor = motor)
class(coche) <- "coche_compuesto"
return(coche)
}
print.coche_compuesto <- function(x, ...) {
cat("Coche modelo:", x$modelo, "\n")
cat("Equipado con: ")
print(x$motor)
}
Veamos cómo funciona:
# Creamos un motor
mi_motor <- crear_motor(120, "gasolina")
# Creamos un coche que contiene ese motor
mi_coche <- crear_coche_compuesto("Sedan", mi_motor)
# Imprimimos el coche
print(mi_coche)
La ventaja de este enfoque es que podemos cambiar fácilmente los componentes:
# Cambiamos el motor del coche
motor_nuevo <- crear_motor(180, "eléctrico")
mi_coche$motor <- motor_nuevo
# Vemos el resultado
print(mi_coche)
Composición en el sistema S4
En S4, la composición se implementa incluyendo objetos de una clase como slots de otra:
library(methods)
# Definimos la clase componente
setClass("Motor",
slots = list(
potencia = "numeric",
tipo = "character"
))
setMethod("show", "Motor",
function(object) {
cat("Motor", object@tipo, "de", object@potencia, "CV\n")
})
# Definimos la clase contenedora
setClass("CocheCompuesto",
slots = list(
modelo = "character",
motor = "Motor" # El coche contiene un motor
))
setMethod("show", "CocheCompuesto",
function(object) {
cat("Coche modelo:", object@modelo, "\n")
cat("Equipado con: ")
show(object@motor)
})
Probemos nuestras clases S4 con composición:
# Creamos un motor
mi_motor_s4 <- new("Motor", potencia = 120, tipo = "gasolina")
# Creamos un coche que contiene ese motor
mi_coche_s4 <- new("CocheCompuesto", modelo = "Sedan", motor = mi_motor_s4)
# Mostramos el coche
show(mi_coche_s4)
Composición en el sistema R6
R6 facilita la implementación de la composición de manera muy natural:
library(R6)
# Definimos la clase componente
Motor <- R6Class("Motor",
public = list(
potencia = NULL,
tipo = NULL,
initialize = function(potencia, tipo) {
self$potencia <- potencia
self$tipo <- tipo
},
describir = function() {
cat("Motor", self$tipo, "de", self$potencia, "CV\n")
}
)
)
# Definimos la clase contenedora
CocheCompuesto <- R6Class("CocheCompuesto",
public = list(
modelo = NULL,
motor = NULL,
initialize = function(modelo, motor) {
self$modelo <- modelo
self$motor <- motor
},
describir = function() {
cat("Coche modelo:", self$modelo, "\n")
cat("Equipado con: ")
self$motor$describir()
},
actualizar_motor = function(nuevo_motor) {
self$motor <- nuevo_motor
cat("Motor actualizado con éxito\n")
}
)
)
Veamos cómo funciona la composición en R6:
# Creamos un motor
mi_motor_r6 <- Motor$new(120, "gasolina")
# Creamos un coche que contiene ese motor
mi_coche_r6 <- CocheCompuesto$new("Sedan", mi_motor_r6)
# Describimos el coche
mi_coche_r6$describir()
# Actualizamos el motor
motor_nuevo_r6 <- Motor$new(180, "eléctrico")
mi_coche_r6$actualizar_motor(motor_nuevo_r6)
# Vemos el resultado
mi_coche_r6$describir()
Composición vs. Herencia: ¿Cuándo usar cada una?
La elección entre composición y herencia depende del tipo de relación que queramos establecer entre nuestros objetos:
Usa herencia cuando:
Existe una clara relación "es un" (un coche es un vehículo)
La subclase realmente es un tipo especializado de la clase base
Quieres reutilizar código de la clase base
Usa composición cuando:
Existe una relación "tiene un" (un coche tiene un motor)
Necesitas más flexibilidad para cambiar comportamientos en tiempo de ejecución
Quieres evitar los problemas de la herencia múltiple
Deseas reducir el acoplamiento entre clases
Ejemplo práctico: Sistema de biblioteca
Veamos un ejemplo más completo que muestra cómo la composición puede ser más flexible que la herencia:
library(R6)
# Definimos componentes reutilizables
Autor <- R6Class("Autor",
public = list(
nombre = NULL,
nacionalidad = NULL,
initialize = function(nombre, nacionalidad) {
self$nombre <- nombre
self$nacionalidad <- nacionalidad
},
describir = function() {
cat("Autor:", self$nombre, "de", self$nacionalidad, "\n")
}
)
)
Editorial <- R6Class("Editorial",
public = list(
nombre = NULL,
pais = NULL,
initialize = function(nombre, pais) {
self$nombre <- nombre
self$pais <- pais
},
describir = function() {
cat("Editorial:", self$nombre, "de", self$pais, "\n")
}
)
)
# Clase principal que usa composición
Libro <- R6Class("Libro",
public = list(
titulo = NULL,
autor = NULL,
editorial = NULL,
año = NULL,
initialize = function(titulo, autor, editorial, año) {
self$titulo <- titulo
self$autor <- autor
self$editorial <- editorial
self$año <- año
},
describir = function() {
cat("Libro:", self$titulo, "publicado en", self$año, "\n")
self$autor$describir()
self$editorial$describir()
},
cambiar_editorial = function(nueva_editorial) {
self$editorial <- nueva_editorial
cat("Editorial actualizada\n")
}
)
)
Usemos estas clases:
# Creamos componentes
autor_garcia <- Autor$new("Gabriel García Márquez", "Colombia")
editorial_original <- Editorial$new("Sudamericana", "Argentina")
editorial_nueva <- Editorial$new("Penguin Random House", "España")
# Creamos un libro usando composición
cien_años <- Libro$new(
"Cien años de soledad",
autor_garcia,
editorial_original,
1967
)
# Describimos el libro
cien_años$describir()
# Cambiamos la editorial fácilmente
cien_años$cambiar_editorial(editorial_nueva)
cien_años$describir()
Patrones de composición avanzados
La composición permite implementar patrones de diseño más flexibles:
Patrón Decorador
El patrón decorador permite añadir funcionalidades a objetos existentes sin modificar su estructura:
# Implementamos un decorador para libros
LibroConDescuento <- R6Class("LibroConDescuento",
public = list(
libro_base = NULL,
porcentaje_descuento = NULL,
initialize = function(libro, porcentaje) {
self$libro_base <- libro
self$porcentaje_descuento <- porcentaje
},
describir = function() {
self$libro_base$describir()
cat("¡Con un descuento del", self$porcentaje_descuento, "%!\n")
}
)
)
# Aplicamos el decorador
libro_oferta <- LibroConDescuento$new(cien_años, 15)
libro_oferta$describir()
Composición dinámica
Podemos cambiar el comportamiento de un objeto en tiempo de ejecución:
# Clase que permite cambiar comportamientos dinámicamente
GestorLibros <- R6Class("GestorLibros",
public = list(
estrategia_busqueda = NULL,
initialize = function(estrategia_inicial) {
self$estrategia_busqueda <- estrategia_inicial
},
cambiar_estrategia = function(nueva_estrategia) {
self$estrategia_busqueda <- nueva_estrategia
},
buscar = function(termino) {
self$estrategia_busqueda$ejecutar(termino)
}
)
)
# Diferentes estrategias de búsqueda
BusquedaPorTitulo <- R6Class("BusquedaPorTitulo",
public = list(
ejecutar = function(termino) {
cat("Buscando libros con título que contenga:", termino, "\n")
}
)
)
BusquedaPorAutor <- R6Class("BusquedaPorAutor",
public = list(
ejecutar = function(termino) {
cat("Buscando libros del autor:", termino, "\n")
}
)
)
# Uso del patrón
gestor <- GestorLibros$new(BusquedaPorTitulo$new())
gestor$buscar("soledad")
# Cambiamos la estrategia en tiempo de ejecución
gestor$cambiar_estrategia(BusquedaPorAutor$new())
gestor$buscar("García Márquez")
Ventajas de la composición sobre la herencia
- Mayor flexibilidad: Puedes cambiar componentes en tiempo de ejecución
- Menor acoplamiento: Las clases están menos vinculadas entre sí
- Evita problemas de herencia múltiple: La composición no sufre los problemas de ambigüedad
- Favorece la reutilización: Los componentes pueden usarse en diferentes contextos
- Facilita las pruebas: Es más fácil probar componentes aislados
La composición sigue el principio de "favorecer la composición sobre la herencia", una recomendación común en el diseño orientado a objetos que promueve estructuras de código más flexibles y mantenibles.
Otros ejercicios de programación de R
Evalúa tus conocimientos de esta lección Herencia y polimorfismo en R con nuestros retos de programación de tipo Test, Puzzle, Código y Proyecto con VSCode, guiados por IA.
Todas las lecciones de R
Accede a todas las lecciones de R y aprende con ejemplos prácticos de código y ejercicios de programación con IDE web sin instalar nada.
Instalación De R Y Rstudio
Introducción Y Entorno
Introducción A R
Introducción Y Entorno
Operadores
Sintaxis
Estructuras De Datos
Sintaxis
Funciones
Sintaxis
Estructuras De Control Iterativo
Sintaxis
Scopes Y Closures
Sintaxis
Estructuras De Control Condicional
Sintaxis
Funciones Anónimas
Sintaxis
Tipos De Datos Y Variables
Sintaxis
Sistema R6: Clases Referenciales Y Encapsulamiento
Programación Orientada A Objetos
Sistema S4: Clases Formales Y Validación
Programación Orientada A Objetos
Herencia Y Polimorfismo En R
Programación Orientada A Objetos
Sistemas De Oop En R
Programación Orientada A Objetos
Sistema S3: Clases Implícitas Y Métodos Genéricos
Programación Orientada A Objetos
Tidyverse Para Transformación De Datos
Manipulación De Datos
Lubridate Para Fechas Y Tiempo
Manipulación De Datos
Group_by Y Summarize Para Agrupación Y Resumen
Manipulación De Datos
Stringr Para Expresiones Regulares
Manipulación De Datos
Tidyr Para Limpieza De Valores Faltantes
Manipulación De Datos
Joins En R Para Combinación Y Relaciones De Tablas
Manipulación De Datos
Pivot_longer Y Pivot_wider Para Reestructuración
Manipulación De Datos
Mutate Y Transmute Para Transformación
Manipulación De Datos
Dplyr Para Filtrado Y Selección
Manipulación De Datos
Readr Y Read.csv Para Importar Datos
Manipulación De Datos
Gráficos Bivariantes En R
Visualización De Datos
Gráficos Univariantes En R
Visualización De Datos
Facetas En Ggplot2
Visualización De Datos
Personalización Y Temas
Visualización De Datos
Ggplot2 Para Visualización De Datos
Visualización De Datos
Gráficos Multivariantes En R
Visualización De Datos
Correlación En R
Estadística
Regresión Lineal En R
Estadística
Pruebas De Hipótesis En R
Estadística
Anova En R
Estadística
Estadística Descriptiva En R
Estadística
En esta lección
Objetivos de aprendizaje de esta lección
- Comprender cómo se implementa la herencia en los sistemas S3, S4 y R6 en R.
- Entender el concepto de polimorfismo y cómo funciona el dispatch de métodos en cada sistema.
- Aprender a implementar composición como alternativa a la herencia en R.
- Diferenciar cuándo es más adecuado usar herencia o composición en el diseño de clases.
- Aplicar patrones de diseño basados en composición para mejorar la flexibilidad y reutilización del código.