Skillversitas

25. Inheritance

Inheritance is the mechanism where a child class (subclass) inherits properties and methods from a parent class (superclass). This enables code reuse and the formation of logical hierarchies.

Why Is Inheritance Important?

Imagine a campus has many roles: Students, Lecturers, Staff. All of them have the properties name, email, and the method getInfo(). Instead of rewriting everything, we create a User class as the parent and inherit from it.

// Without inheritance — duplicate code
class Student {
  constructor(name, email) { this.name = name; this.email = email; }
  getInfo() { return `${this.name} - ${this.email}`; }
}
class Lecturer {
  constructor(name, email) { this.name = name; this.email = email; }
  getInfo() { return `${this.name} - ${this.email}`; }
}

// With inheritance — reusable code
class User {
  constructor(name, email) { this.name = name; this.email = email; }
  getInfo() { return `${this.name} - ${this.email}`; }
}
class Student extends User {}
class Lecturer extends User {}

Code Example

extends and super

class User {
  constructor(name, email) {
    this.name = name;
    this.email = email;
    this.registrationDate = new Date();
  }

  getInfo() {
    return `${this.name} (${this.email})`;
  }

  getRegistrationDateFormat() {
    return this.registrationDate.toLocaleDateString("en-US");
  }
}

class Student extends User {
  constructor(name, email, studentId, major) {
    super(name, email); // call the parent constructor
    this.studentId = studentId;
    this.major = major;
    this.gpa = 0;
    this.courseList = [];
  }

  getInfo() {
    return `${super.getInfo()} | StudentID: ${this.studentId} | ${this.major}`;
  }

  enrollInCourse(courseName) {
    this.courseList.push(courseName);
    return ` enrolls in `;
  }
}

const student = new Student(
  "Mike Johnson", "[email protected]", "2024001", "Computer Science"
);
console.log(student.getInfo());
// "Mike Johnson ([email protected]) | StudentID: 2024001 | Computer Science"
console.log(student.getRegistrationDateFormat()); // "14/7/2026"

Multi-Level Inheritance

class User {
  constructor(name, email) {
    this.name = name;
    this.email = email;
  }

  getInfo() {
    return `${this.name} <${this.email}>`;
  }

  getRole() {
    return "User";
  }
}

class Student extends User {
  constructor(name, email, studentId) {
    super(name, email);
    this.studentId = studentId;
    this.gpa = 0;
    this.status = "Active";
  }

  getRole() {
    return "Student";
  }

  getTranscript() {
    return `Transcript: ${this.name} - GPA: ${this.gpa}`;
  }
}

class StudentReguler extends Student {
  constructor(name, email, studentId, myClass) {
    super(name, email, studentId);
    this.myClass = myClass;
    this.type = "Reguler";
  }

  getRole() {
    return "Student Reguler";
  }

  getJadwal() {
    return `Class ${this.myClass}: Monday-Thursday`;
  }
}

class StudentGraduate extends Student {
  constructor(name, email, studentId, studyProgram) {
    super(name, email, studentId);
    this.studyProgram = studyProgram;
    this.type = "Graduate";
    this.researchStatus = "Active";
  }

  getRole() {
    return "Graduate Student";
  }

  getResearchStatus() {
    return `${this.name} - Status: ${this.researchStatus}`;
  }
}

// Usage
const reguler = new StudentReguler(
  "Mike", "[email protected]", "2024001", "CS-A"
);
const graduateStudent = new StudentGraduate(
  "Dr. Anna", "[email protected]", "P2024001", "M.S. Computer Science"
);

console.log(reguler.getRole());       // "Student Reguler"
console.log(reguler.getJadwal());     // "Class CS-A: Monday-Thursday"
console.log(reguler.getInfo());       // inherited from User

console.log(graduateStudent.getRole());  // "Graduate Student"
console.log(graduateStudent.getTranscript()); // inherited from Student

Method Overriding

class Lecturer extends User {
  constructor(name, email, nidn, course) {
    super(name, email);
    this.nidn = nidn;
    this.course = course || [];
    this.consultationSchedule = [];
  }

  // Override getRole()
  getRole() {
    return "Lecturer";
  }

  // Override getInfo() — add lecturer info
  getInfo() {
    return `Dr. ${super.getInfo()} | NIDN: ${this.nidn}`;
  }

  addConsultationSchedule(day, time) {
    this.consultationSchedule.push({ day, time });
    return `Consultation added: ${day} ${time}`;
  }

  // Static method
  static dariData(data) {
    return new Lecturer(data.name, data.email, data.nidn, data.mk);
  }
}

const lecturerData = {
  name: "John Smith",
  email: "[email protected]",
  nidn: "0012345678",
  mk: ["Database", "Networking"]
};

const lecturer = Lecturer.dariData(lecturerData);
console.log(lecturer.getInfo());
// "Dr. John Smith <[email protected]> | NIDN: 0012345678"
console.log(lecturer.getRole()); // "Lecturer"

instanceof — Checking the Inheritance Type

const user = new User("Test", "[email protected]");
const student = new StudentReguler("Mike", "[email protected]", "001", "CS-A");

console.log(student instanceof StudentReguler); // true
console.log(student instanceof Student);        // true
console.log(student instanceof User);             // true
console.log(user instanceof Student);       // false

Inheritance with Built-in Classes

class GradeList extends Array {
  constructor(studentName) {
    super();
    this.studentName = studentName;
  }

  getAverage() {
    if (this.length === 0) return 0;
    const total = this.reduce((sum, v) => sum + v, 0);
    return (total / this.length).toFixed(2);
  }

  getHighest() {
    return Math.max(...this);
  }

  getLowest() {
    return Math.min(...this);
  }

  getFormat() {
    return this.map((v, i) => `Semester ${i + 1}: ${v}`).join(", ");
  }
}

const gradeMike = new GradeList("Mike Johnson");
gradeMike.push(3.5);
gradeMike.push(3.8);
gradeMike.push(3.9);

console.log(gradeMike.length);          // 3 (method from Array)
console.log(gradeMike.getAverage());   // "3.73"
console.log(gradeMike.getFormat());     // "Semester 1: 3.5, Semester 2: 3.8, ..."

Code Explanation

Concept Explanation
extends Declares a child class that inherits from a parent
super() Calls the parent constructor/method — required in the child constructor
super.method() Calls the parent method from inside an overriding method
Overriding The child defines a method with the same name → replaces the parent's
instanceof Checks whether an object is an instance of a given class (including parent classes)

Inheritance Hierarchy at a Campus

User (base)
├── Student
│   ├── StudentReguler
│   └── StudentGraduate
├── Lecturer
│   ├── PermanentFaculty
│   └── PracticumFaculty
└── Staff
    ├── StaffAdmin
    └── StaffLab

Real-World Examples

An academic system with different roles:

class User {
  constructor(name, email) {
    this.name = name;
    this.email = email;
  }

  getInfo() {
    return `${this.name} <${this.email}>`;
  }
}

class Student extends User {
  constructor(name, email, studentId, major) {
    super(name, email);
    this.studentId = studentId;
    this.major = major;
    this.coursesTaken = [];
    this.gradePerCourse = {};
  }

  enrollInCourse(course) {
    if (this.coursesTaken.length >= 6) {
      return "Maximum of 6 courses!";
    }
    this.coursesTaken.push(course);
    return `${course} enrolled`;
  }

  inputGrade(course, grade) {
    this.gradePerCourse[course] = grade;
  }

  calculateGPA() {
    const gradeArray = Object.values(this.gradePerCourse);
    if (gradeArray.length === 0) return 0;
    return (gradeArray.reduce((a, b) => a + b, 0) / gradeArray.length).toFixed(2);
  }

  getTranscript() {
    let transcript = `\n=== Transcript: ${this.name} (${this.studentId}) ===\n`;
    for (const [mk, grade] of Object.entries(this.gradePerCourse)) {
      transcript += `  ${mk}: ${grade}\n`;
    }
    transcript += `  GPA: ${this.calculateGPA()}\n`;
    return transcript;
  }
}

// Usage
const mike = new Student("Mike", "mike.edu", "2024001", "CS");

mike.enrollInCourse("Algorithms");
mike.enrollInCourse("Web Programming");
mike.enrollInCourse("Database");

mike.inputGrade("Algorithms", 3.8);
mike.inputGrade("Web Programming", 3.5);
mike.inputGrade("Database", 3.9);

console.log(mike.getTranscript());
// === Transcript: Mike (2024001) ===
//   Algorithms: 3.8
//   Web Programming: 3.5
//   Database: 3.9
//   GPA: 3.73

Conclusion

  • extends connects a child to a parent — the child inherits all methods and properties.
  • super() must be called in the child constructor before using this.
  • Method overriding lets a child replace a parent method's behavior.
  • Multi-level inheritance allows chains: User → Student → StudentReguler.
  • Use instanceof to check an object's type within an inheritance hierarchy.