Plataforma de E-Learning
Parte de la sección Programación Orientada a Objetos del Journey de Java de Coddy — lección 84 de 87.
¡Bienvenido al capítulo de Desafíos Finales! Estos desafíos están diseñados para poner a prueba tu dominio de todos los conceptos de OOP que has aprendido a lo largo de este curso.
En este desafío, construirás un sistema de Plataforma de E-Learning que combina herencia, interfaces, polimorfismo, encapsulamiento y patrones de diseño en una aplicación cohesiva.
Tu plataforma debe modelar las relaciones entre cursos, estudiantes e instructores. Piensa en cómo una clase base User puede ser extendida por las clases Student e Instructor, cómo los cursos contienen lecciones y cómo funciona el seguimiento de inscripciones entre estudiantes y cursos.
Considera qué principios de OOP se aplican: utiliza el encapsulamiento para proteger los datos del usuario, la herencia para compartir comportamientos comunes, interfaces para definir contratos como Enrollable o Completable, y el polimorfismo para manejar diferentes tipos de usuarios de manera uniforme.
¡Buena suerte aplicando todo lo que has aprendido!
Desafío
Fácil¡Vamos a construir una Plataforma de E-Learning que reúna todos los conceptos de OOP que has dominado a lo largo de este curso! Crearás un sistema que modele las relaciones entre cursos, estudiantes e instructores utilizando herencia, interfaces, polimorfismo y encapsulamiento.
Organizarás tu código en seis archivos:
Enrollable.java: Crea una interfaz que defina el contrato para las operaciones de inscripción. Debe declarar los métodosenroll(Student student)que devuelve un booleano, ygetEnrolledCount()que devuelve un int.User.java: Crea una clase base abstracta que represente a cualquier usuario en la plataforma. Incluye campos privados paraid(String) yname(String), un constructor que inicialice ambos, los getters apropiados y un método abstractogetRole()que devuelva un String describiendo el rol del usuario.Student.java: Crea una clase que extienda deUser. Añade un ArrayList privado para rastrear los IDs de los cursos inscritos. Incluye un constructor que llame al constructor del padre, implementagetRole()para que devuelva"Student", y añade los métodosaddCourse(String courseId)ygetEnrolledCourseCount(). SobrescribetoString()para que devuelva"Student: [name] ([enrolledCount] courses)".Instructor.java: Crea una clase que extienda deUser. Añade un campo privado paraspecialty(String). Incluye un constructor que reciba id, name y specialty, implementagetRole()para que devuelva"Instructor", añade un getter para specialty y sobrescribetoString()para que devuelva"Instructor: [name] - [specialty]".Course.java: Crea una clase que implementeEnrollable. Incluye campos privados paracourseId(String),title(String),instructor(Instructor) y un ArrayList de Students inscritos. El constructor recibe courseId, title e instructor. Implementaenroll(Student student)para añadir al estudiante a la lista, llama al métodoaddCourse()del estudiante con el ID de este curso y devuelve true. ImplementagetEnrolledCount(). Añade un métodogetDetails()que devuelva"[courseId] [title] by [instructorName]".Main.java: ¡Construye tu plataforma! Recibirás una cadena de comandos separados por comas:ADD_INSTRUCTOR:id:name:specialtyADD_STUDENT:id:nameADD_COURSE:courseId:title:instructorIdENROLL:studentId:courseIdINFO:userId
Mantén colecciones de instructores, estudiantes y cursos. Procesa cada comando e imprime:
- ADD_INSTRUCTOR:
Instructor added: [name] - ADD_STUDENT:
Student added: [name] - ADD_COURSE:
Course added: [title] - ENROLL:
[studentName] enrolled in [courseTitle] - INFO: Imprime la salida del
toString()del usuario
Después de todos los comandos, imprime
--- Platform Summary ---seguido de los detalles de cada curso y el recuento de inscritos en el formato[courseDetails] - [count] student(s).
Recibirás una entrada: la cadena de comandos separados por comas.
Por ejemplo, con la entrada ADD_INSTRUCTOR:I001:Dr. Smith:Java,ADD_STUDENT:S001:Alice,ADD_STUDENT:S002:Bob,ADD_COURSE:C001:OOP Fundamentals:I001,ENROLL:S001:C001,ENROLL:S002:C001,INFO:S001,INFO:I001, tu salida sería:
Instructor added: Dr. Smith
Student added: Alice
Student added: Bob
Course added: OOP Fundamentals
Alice enrolled in OOP Fundamentals
Bob enrolled in OOP Fundamentals
Student: Alice (1 courses)
Instructor: Dr. Smith - Java
--- Platform Summary ---
[C001] OOP Fundamentals by Dr. Smith - 2 student(s)¡Este desafío combina herencia (jerarquía User), interfaces (Enrollable), polimorfismo (diferentes tipos de usuario con sus propias implementaciones de toString) y encapsulamiento (campos privados con acceso controlado) en un sistema cohesivo!
Hoja de referencia
Este desafío final combina múltiples conceptos de POO en un sistema cohesivo:
Interfaces
Define contratos para el comportamiento que las clases deben implementar:
public interface Enrollable {
boolean enroll(Student student);
int getEnrolledCount();
}Clases Abstractas
Crea clases base con comportamiento compartido y métodos abstractos:
public abstract class User {
private String id;
private String name;
public User(String id, String name) {
this.id = id;
this.name = name;
}
public abstract String getRole();
}Herencia
Extiende clases base para crear tipos especializados:
public class Student extends User {
private ArrayList<String> enrolledCourses;
public Student(String id, String name) {
super(id, name);
this.enrolledCourses = new ArrayList<>();
}
@Override
public String getRole() {
return "Student";
}
}Implementación de Interfaces
Las clases pueden implementar interfaces para cumplir con los contratos:
public class Course implements Enrollable {
private ArrayList<Student> enrolledStudents;
@Override
public boolean enroll(Student student) {
enrolledStudents.add(student);
student.addCourse(courseId);
return true;
}
@Override
public int getEnrolledCount() {
return enrolledStudents.size();
}
}Polimorfismo
Diferentes clases pueden sobrescribir métodos para proporcionar un comportamiento especializado:
@Override
public String toString() {
return "Student: " + name + " (" + enrolledCourses.size() + " courses)";
}Encapsulamiento
Usa campos privados con acceso controlado a través de métodos para proteger la integridad de los datos y mantener las relaciones entre los objetos.
Pruébalo tú mismo
import java.util.Scanner;
import java.util.HashMap;
import java.util.ArrayList;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String input = scanner.nextLine();
// TODO: Crear colecciones para almacenar instructores, estudiantes y cursos
// Hint: Usa HashMap con id como clave para una búsqueda fácil
// TODO: Dividir la entrada por comas para obtener comandos individuales
// TODO: Procesar cada comando:
// - ADD_INSTRUCTOR:id:name:specialty -> Crear instructor, añadir a la colección, imprimir "Instructor added: [name]"
// - ADD_STUDENT:id:name -> Crear estudiante, añadir a la colección, imprimir "Student added: [name]"
// - ADD_COURSE:courseId:title:instructorId -> Crear curso con instructor, añadir a la colección, imprimir "Course added: [title]"
// - ENROLL:studentId:courseId -> Matricular estudiante en el curso, imprimir "[studentName] enrolled in [courseTitle]"
// - INFO:userId -> Buscar usuario (estudiante o instructor) e imprimir su toString()
// TODO: Después de procesar todos los comandos, imprimir "--- Platform Summary ---"
// TODO: Para cada curso, imprimir "[courseDetails] - [count] student(s)"
}
}
Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.
Todas las lecciones de Programación Orientada a Objetos
1Fundamentos de OOP
Archivos externosIntroducción a la OOPClases vs. ObjetosLa palabra clave thisMétodosCampos (Atributos)Método constructorSobrecarga de constructoresResumen - Calculadora simple4Herencia
Herencia básica (extends)La palabra clave superSobrescritura de métodos (@Override)Encadenamiento de constructoresLa clase ObjectHerencia simple y multinivelPor qué no hay herencia múltiple de clasesResumen - Jerarquía de empleados7Métodos especiales y la clase Object
Método toString()equals() y hashCode()Método clone()compareTo() y ComparableInterfaz ComparatorResumen - Ordenamiento personalizado2Modificadores de acceso y encapsulamiento
Visión general de los niveles de accesoMétodos Getter y SetterOcultamiento de informaciónLa palabra clave finalResumen - Gestor de cuentas bancarias5Polimorfismo
Fundamentos de sobrecarga de métodosSobrescritura de métodos (tiempo de ejecución)Upcasting y DowncastingEl operador instanceofClases y métodos abstractosResumen - Calculadora de figuras8Conceptos avanzados de POO
Composición vs. HerenciaAgregación vs. ComposiciónClases internas, anidadas y anónimasEnums y métodos de EnumRecords (Java 16+)Clases selladas (Java 17+)11Patrones de diseño - Parte 1
Introducción a los patrones de diseñoPatrón SingletonPatrón FactoryPatrón BuilderPatrón ObserverPatrón Strategy14Desafíos finales
Plataforma de E-LearningSistema bancarioDesarrollo de personajes de videojuegosServicio de alquiler de vehículos3Propiedades de clase y miembros estáticos
Variables de instancia vs. estáticasMétodos estáticosBloques estáticosConstantes (static final)Repaso - Contador y utilidad6Interfaces y Clases Abstractas
Introducción a las InterfacesImplementación de InterfacesImplementación de Múltiples InterfacesMétodos Default y Static en InterfacesClases Abstractas vs InterfacesInterfaces FuncionalesResumen - Sistema de Pagos9Genéricos
Introducción a los genéricosClases genéricasMétodos genéricosParámetros de tipo delimitadosComodines (?, extends, super)Resumen - Contenedor genérico12Patrones de diseño Parte 2
Patrón CommandPatrón AdapterPatrón DecoratorPatrón Template MethodPatrón StatePatrón CompositePatrón Iterator