Menu
CoddyTech

在线学习平台

本课属于 Coddy Java 学习旅程的“面向对象编程”单元。第 84 课,共 87 课。

欢迎来到最终挑战章!这些挑战旨在检验你对本课程所学全部 OOP 概念的掌握程度。

在这个挑战中,你将构建一个在线学习平台系统,将继承、接口、多态、封装和设计模式整合到一个完整的应用程序中。

你的平台应该对课程、学生和讲师之间的关系进行建模。想一想如何通过 Student 和 Instructor 类扩展 User 基类,课程如何包含课,以及如何跟踪学生和课程之间的选课情况。

思考一下适用哪些 OOP 原则:使用封装来保护用户数据,使用继承来共享通用行为,使用接口来定义契约,例如 Enrollable 或 Completable,并使用多态来统一处理不同的用户类型。

祝你顺利运用所学的一切!

challenge icon

挑战

简单

让我们构建一个电子学习平台,把你在这门课程中掌握的所有 OOP 概念结合起来!你将使用继承、接口、多态和封装,创建一个模拟课程、学生和讲师之间关系的系统。

你将把代码分布在 6 个文件中:

  • Enrollable.java:创建一个定义注册操作规范的接口。它应声明方法 enroll(Student student),该方法返回 boolean;还应声明方法 getEnrolledCount(),该方法返回 int。
  • User.java:创建一个抽象基类,用于表示平台上的所有用户。添加私有字段 id(String)和 name(String),添加一个用于初始化这两个字段的构造函数、合适的 getter,以及一个抽象方法 getRole(),用于返回描述用户角色的 String。
  • Student.java:创建一个继承 User 的类。添加一个私有 ArrayList,用于记录已注册课程的 ID。添加一个调用父类构造函数的构造函数,实现 getRole() 并使其返回 "Student",再添加方法 addCourse(String courseId) 和 getEnrolledCourseCount()。重写 toString(),使其返回 "Student: [name] ([enrolledCount] courses)"。
  • Instructor.java:创建一个继承 User 的类。添加一个私有字段 specialty(String)。添加一个接收 id、name 和 specialty 的构造函数,实现 getRole() 并使其返回 "Instructor",为 specialty 添加 getter,并重写 toString(),使其返回 "Instructor: [name] - [specialty]"。
  • Course.java:创建一个实现 Enrollable 的类。添加私有字段 courseId(String)、title(String)、instructor(Instructor),以及一个用于存储已注册学生的 ArrayList。构造函数接收 courseId、title 和 instructor。实现 enroll(Student student),将学生添加到列表中,调用该学生的 addCourse() 方法并传入本课程的 ID,然后返回 true。实现 getEnrolledCount()。添加方法 getDetails(),使其返回用字面方括号括起来的课程 ID,后接课程标题和讲师姓名,格式为 "[" + courseId + "] " + title + " by " + instructorName。
  • Main.java:构建你的平台!你将收到一个以逗号分隔的命令字符串:
    • ADD_INSTRUCTOR:id:name:specialty
    • ADD_STUDENT:id:name
    • ADD_COURSE:courseId:title:instructorId
    • ENROLL:studentId:courseId
    • INFO:userId

    维护讲师、学生和课程的集合。处理每条命令并打印:

    • ADD_INSTRUCTOR:Instructor added: [name]
    • ADD_STUDENT:Student added: [name]
    • ADD_COURSE:Course added: [title]
    • ENROLL:[studentName] enrolled in [courseTitle]
    • INFO:打印用户的 toString() 输出

    处理完所有命令后,打印 --- Platform Summary ---,然后按格式 [courseDetails] - [count] student(s) 打印每门课程的详细信息和注册人数。

你将收到一个输入:以逗号分隔的命令字符串。

例如,输入为 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 时,输出为:

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)

这个挑战将继承(User 层次结构)、接口(Enrollable)、多态(不同用户类型各自实现 toString)和封装(通过私有字段控制访问)结合起来,构建成一个完整的系统!

亲手试试

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: 创建集合,存储教师、学生和课程
        // 提示:使用 HashMap,以 id 为键,方便查找
        
        // TODO: 按逗号拆分 input,得到各个命令
        
        // TODO: 处理每个命令:
        // ADD_INSTRUCTOR:id:name:specialty:创建教师并加入集合,打印 "Instructor added: [name]"
        // ADD_STUDENT:id:name:创建学生并加入集合,打印 "Student added: [name]"
        // ADD_COURSE:courseId:title:instructorId:创建带有教师的课程并加入集合,打印 "Course added: [title]"
        // ENROLL:studentId:courseId:让学生选修课程,打印 "[studentName] enrolled in [courseTitle]"
        // INFO:userId:查找用户(学生或教师)并打印其 toString()
        
        // TODO: 处理完所有命令后,打印 "--- Platform Summary ---"
        
        // TODO: 对每门课程,打印 "[courseDetails] - [count] student(s)"
    }
}
quiz icon自我测试

这节课包含一个小测验。开始学习即可作答,并记录你的进度。

面向对象编程中的所有课

自己练习: Java 在线编译器