OOP - 캡슐화

Patricia Arquette
Patricia Arquette원래의
2024-12-14 17:39:11729검색

OOP - Encapsulation

뭐???

캡슐화는 데이터와 기능을 단일 단위(예: 캡슐)로 묶는 프로세스이며, 일부 데이터/메서드에 대한 액세스를 제한할 수도 있습니다.

상속, 다형성, 데이터 추상화와 함께 OOP의 4대 핵심 중 하나입니다.

왜?

맹목적인 가정을 하고 모든 위치에서 캡슐화를 사용하여 진행하는 것이 더 쉽지만 올바른 방법으로 사용하려면 그 이유를 이해하는 것이 중요합니다.

예제 작업을 통해 이유를 이해해 보겠습니다.

일:

학생 결과 계산기를 만들어 보세요

  • 평균점수 계산
  • 학생의 불합격 또는 합격 여부 확인
  • 주제 표시가 유효하지 않은 경우 오류 발생(< 0 || > 100)

해결책 1: 캡슐화되지 않은 방식

단순히 문제를 해결하는 것이 아이디어이므로 좋은 대비를 보여주고 문제를 더욱 명확하게 보이게 할 수 있는 절차적 프로그래밍 달성 방법을 선택했습니다.

type Subject = "english" | "maths";

interface IStudent {
  name: string;
  marks: Record<Subject, number>;
}

// Receive Input
const studentInput: IStudent = {
  name: "John",
  marks: {
    english: 100,
    maths: 100,
  },
};

// Step1: Validate the provided marks
Object.keys(studentInput.marks).forEach((subjectName) => {
  const mark = studentInput.marks[subjectName as Subject];
  if (mark > 100 || mark < 0) {
    throw new Error(`invlid mark found`);
  }
});

// Step2: find the total marks
const totalMarks = Object.keys(studentInput.marks).reduce(
  (accumulator: number, current: string) =>
    studentInput.marks[current as Subject] + accumulator,
  0
);

// Step3: find the average
const average = totalMarks / Object.keys(studentInput.marks).length;

// Step4: find the result
const boolResult = average > 40;

// Step 5: print result
console.log(boolResult);
console.log(average);

해결책 1의 문제:

이것은 확실히 기대했던 결과를 달성하지만 그에 관련된 몇 가지 문제가 있습니다. 몇 가지 예를 들면

  1. 여기의 모든 구현은 전 세계적으로 액세스 가능하며 향후 기여자의 사용을 제어할 수 없습니다.
  2. 데이터와 작업은 별개이므로 어떤 기능이 데이터에 영향을 미치는지 추적하기 어렵습니다. 호출되는 내용과 실행의 일부를 이해하려면 모든 코드를 주의 깊게 검토해야 합니다.
  3. 로직이 확장되면 함수를 관리하기가 더 어려워집니다. 긴밀한 결합으로 인해 변경 사항으로 인해 관련 없는 코드가 손상될 수 있습니다.

문제를 해결하는 방법?

캡슐화를 통합하거나 아래 두 단계를 수행하여 더욱 명확하게 만듭니다.

  1. 데이터 및 기능에 대한 액세스 제어
  2. 행동과 데이터 묶음

해결책 2: 캡슐화 방식

type SubjectNames = "english" | "maths";

interface IStudent {
  name: string;
  marks: Record<SubjectNames, number>;
}

class ResultCalculator {
  protected student: IStudent;
  constructor(student: IStudent) {
    this.student = student;
  }

  isPassed(): boolean {
    let resultStatus = true;
    Object.keys(this.student.marks).forEach((subject: string) => {
      if (this.student.marks[subject as SubjectNames] < 40) {
        resultStatus = false;
      }
    });
    return resultStatus;
  }

  getAverage(): number {
    this.validateMarks();
    return this.totalMarks() / this.subjectCount();
  }

  private validateMarks() {
    Object.keys(this.student.marks).forEach((subject: string) => {
      if (
        this.student.marks[subject as SubjectNames] < 0 ||
        this.student.marks[subject as SubjectNames] > 100
      ) {
        throw new Error(`invalid mark`);
      }
    });
  }

  private totalMarks() {
    return Object.keys(this.student.marks).reduce(
      (acc, curr) => this.student.marks[curr as SubjectNames] + acc,
      0
    );
  }

  private subjectCount() {
    return Object.keys(this.student.marks).length;
  }
}

// Receive Input
const a: IStudent = {
  name: "jingleheimer schmidt",
  marks: {
    english: 100,
    maths: 100,
  },
};

// Create an encapsulated object
const result = new ResultCalculator(a);

// Perform operations & print results
console.log(result.isPassed());
console.log(result.getAverage());

위 솔루션에서 공지사항

  1. 메서드 totalMarks, subjectCount, verifyMarks 및 멤버 변수 학생은 노출되지 않으며 클래스 개체에서만 사용할 수 있습니다.

2. 데이터 학생은 모든 동작과 함께 번들로 제공됩니다.

위 내용은 OOP - 캡슐화의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.