Menu
Coddy logo textTech

E-러닝 플랫폼

Coddy Java 여정의 객체 지향 프로그래밍 섹션에 포함된 레슨 — 87개 중 84번째.

최종 챌린지 챕터에 오신 것을 환영합니다! 이 챌린지들은 이 코스 전반에서 배운 모든 OOP 개념에 대한 숙련도를 테스트하도록 설계되었습니다.

이 챌린지에서 여러분은 상속, 인터페이스, 다형성, 캡슐화 및 디자인 패턴을 응집력 있는 애플리케이션으로 결합한 이러닝 플랫폼(E-Learning Platform) 시스템을 구축하게 됩니다.

여러분의 플랫폼은 강좌, 학생, 강사 간의 관계를 모델링해야 합니다. User 기본 클래스가 StudentInstructor 클래스에 의해 어떻게 확장될 수 있는지, 강좌가 어떻게 레슨을 포함하는지, 그리고 학생과 강좌 간의 수강 등록 추적이 어떻게 작동하는지 생각해 보세요.

어떤 OOP 원칙이 적용되는지 고려해 보세요: 사용자 데이터를 보호하기 위해 캡슐화(encapsulation)를 사용하고, 공통된 동작을 공유하기 위해 상속(inheritance)을 사용하며, Enrollable 또는 Completable과 같은 계약을 정의하기 위해 인터페이스(interfaces)를 사용하고, 다양한 사용자 유형을 일관되게 처리하기 위해 다형성(polymorphism)을 사용하세요.

배운 내용을 잘 적용해 보시기 바랍니다!

challenge icon

챌린지

쉬움

이 과정에서 마스터한 모든 OOP 개념을 하나로 모으는 E-Learning 플랫폼을 구축해 봅시다! 상속, 인터페이스, 다형성 및 캡슐화를 사용하여 강좌, 학생 및 강사 간의 관계를 모델링하는 시스템을 만들게 됩니다.

코드는 다음 6개의 파일로 구성됩니다:

  • Enrollable.java: 등록 작업을 위한 계약을 정의하는 인터페이스를 만듭니다. boolean을 반환하는 enroll(Student student) 메서드와 int를 반환하는 getEnrolledCount() 메서드를 선언해야 합니다.
  • User.java: 플랫폼의 모든 사용자를 나타내는 추상 베이스 클래스를 만듭니다. id (String)와 name (String)을 위한 private 필드, 이 둘을 초기화하는 생성자, 적절한 getter, 그리고 사용자의 역할을 설명하는 String을 반환하는 추상 메서드 getRole()을 포함합니다.
  • Student.java: User를 상속받는 클래스를 만듭니다. 등록된 강좌 ID를 추적하기 위한 private ArrayList를 추가합니다. 부모 생성자를 호출하는 생성자를 포함하고, getRole()"Student"를 반환하도록 구현하며, addCourse(String courseId)getEnrolledCourseCount() 메서드를 추가합니다. toString()을 오버라이드하여 "Student: [name] ([enrolledCount] courses)"를 반환하도록 합니다.
  • Instructor.java: User를 상속받는 클래스를 만듭니다. specialty (String)를 위한 private 필드를 추가합니다. id, name, specialty를 인자로 받는 생성자를 포함하고, getRole()"Instructor"를 반환하도록 구현하며, specialty에 대한 getter를 추가하고, toString()을 오버라이드하여 "Instructor: [name] - [specialty]"를 반환하도록 합니다.
  • Course.java: Enrollable을 구현하는 클래스를 만듭니다. courseId (String), title (String), instructor (Instructor)를 위한 private 필드와 등록된 학생들의 ArrayList를 포함합니다. 생성자는 courseId, title, instructor를 인자로 받습니다. enroll(Student student)를 구현하여 학생을 리스트에 추가하고, 해당 학생의 addCourse() 메서드를 이 강좌의 ID와 함께 호출한 뒤 true를 반환합니다. getEnrolledCount()를 구현합니다. "[courseId] [title] by [instructorName]"을 반환하는 getDetails() 메서드를 추가합니다.
  • 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 구현을 가진 서로 다른 사용자 유형), 그리고 캡슐화(제어된 액세스를 가진 private 필드)를 하나의 응집력 있는 시스템으로 결합합니다!

치트 시트

이 마지막 챌린지는 여러 OOP 개념을 하나의 응집력 있는 시스템으로 결합합니다:

인터페이스 (Interfaces)

클래스가 반드시 구현해야 하는 동작에 대한 계약을 정의합니다:

public interface Enrollable {
    boolean enroll(Student student);
    int getEnrolledCount();
}

추상 클래스 (Abstract Classes)

공유된 동작과 추상 메서드를 가진 기본 클래스를 생성합니다:

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();
}

상속 (Inheritance)

기본 클래스를 확장하여 특수화된 타입을 생성합니다:

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";
    }
}

인터페이스 구현 (Implementing Interfaces)

클래스는 계약을 이행하기 위해 인터페이스를 구현할 수 있습니다:

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();
    }
}

다형성 (Polymorphism)

서로 다른 클래스가 메서드를 오버라이드하여 특수화된 동작을 제공할 수 있습니다:

@Override
public String toString() {
    return "Student: " + name + " (" + enrolledCourses.size() + " courses)";
}

캡슐화 (Encapsulation)

데이터 무결성을 보호하고 객체 간의 관계를 유지하기 위해 메서드를 통한 제어된 접근과 함께 private 필드를 사용합니다.

직접 해보기

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: 강사, 학생, 강좌를 저장할 컬렉션을 생성하세요
        // Hint: 쉬운 조회를 위해 id를 키로 사용하는 HashMap을 사용하세요
        
        // TODO: 입력을 쉼표로 분할하여 개별 명령어를 가져오세요
        
        // 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실력 점검

이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.

객체 지향 프로그래밍의 모든 레슨