Menu
Coddy logo textTech

Eラーニングプラットフォーム

CoddyのJavaジャーニー「オブジェクト指向プログラミング」セクションの一部 — レッスン 84/87。

「最終チャレンジ」の章へようこそ!これらのチャレンジは、このコース全体で学んだすべてのOOPコンセプトの習熟度をテストするように設計されています。

このチャレンジでは、継承、インターフェース、ポリモーフィズム、カプセル化、およびデザインパターンを1つのまとまりのあるアプリケーションに組み合わせたeラーニングプラットフォームシステムを構築します。

あなたのプラットフォームでは、コース、学生、講師の間の関係をモデル化する必要があります。UserベースクラスをStudentクラスやInstructorクラスでどのように拡張できるか、コースがどのようにレッスンを保持するか、そして学生とコースの間の受講登録の追跡がどのように機能するかを考えてみましょう。

どのOOP原則が適用されるか検討してください。ユーザーデータを保護するためにカプセル化を、共通の動作を共有するために継承を、EnrollableCompletable のようなコントラクトを定義するためにインターフェースを、そして異なるユーザータイプを一律に扱うためにポリモーフィズムを使用します。

学んだことをすべて活かして、頑張ってください!

challenge icon

チャレンジ

簡単

このコースで習得したすべてのOOP(オブジェクト指向プログラミング)の概念を統合した、Eラーニングプラットフォームを構築しましょう!継承、インターフェース、ポリモーフィズム、およびカプセル化を使用して、コース、学生、および講師の間の関係をモデル化するシステムを作成します。

コードは以下の6つのファイルに分けて構成します:

  • Enrollable.java: 登録操作の規約を定義するインターフェースを作成します。booleanを返す enroll(Student student) メソッドと、intを返す getEnrolledCount() メソッドを宣言する必要があります。
  • User.java: プラットフォーム上の任意のユーザーを表す抽象基底クラスを作成します。id (String) と name (String) のプライベートフィールド、両方を初期化するコンストラクタ、適切なゲッター、およびユーザーの役割を説明するStringを返す抽象メソッド getRole() を含めます。
  • Student.java: User を継承するクラスを作成します。登録されたコースIDを追跡するためのプライベートな ArrayList を追加します。親コンストラクタを呼び出すコンストラクタを含め、getRole() を実装して "Student" を返すようにし、addCourse(String courseId) メソッドと getEnrolledCourseCount() メソッドを追加します。toString() をオーバーライドして、"Student: [name] ([enrolledCount] courses)" を返すようにします。
  • Instructor.java: User を継承するクラスを作成します。specialty (String) のプライベートフィールドを追加します。id、name、specialtyを受け取るコンストラクタを含め、getRole() を実装して "Instructor" を返すようにし、specialtyのゲッターを追加し、toString() をオーバーライドして "Instructor: [name] - [specialty]" を返すようにします。
  • Course.java: Enrollable を実装するクラスを作成します。courseId (String)、title (String)、instructor (Instructor)、および登録された学生の 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) の形式で出力します。

入力として、カンマ区切りのコマンド文字列を1つ受け取ります。

例えば、入力が 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 実装を持つ異なるユーザータイプ)、およびカプセル化(アクセス制御されたプライベートフィールド)を1つのまとまりのあるシステムに統合するものです!

チートシート

この最終チャレンジでは、複数のOOPコンセプトを組み合わせて、まとまりのあるシステムを構築します:

インターフェース

クラスが実装しなければならない振る舞いの契約を定義します:

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

抽象クラス

共有される振る舞いと抽象メソッドを持つベースクラスを作成します:

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

継承

ベースクラスを拡張して、特化した型を作成します:

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

インターフェースの実装

クラスはインターフェースを実装することで、契約を果たすことができます:

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

ポリモーフィズム

異なるクラスがメソッドをオーバーライドして、特化した振る舞いを提供できます:

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

カプセル化

メソッドを介した制御されたアクセスを持つプライベートフィールドを使用して、データの整合性を保護し、オブジェクト間の関係を維持します。

自分で試してみよう

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腕試し

このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。

オブジェクト指向プログラミングのすべてのレッスン