Elice

엘리스 8일차 - 상속과 캡슐화

공부곤 2024. 7. 3. 14:44

상속과 캡슐화

상속(Inheritance)

  • 기존에 존재하던 클래스의 멤버 변수와 메서드를 그대로 물려받아, 멤버 변수 및 메서드를 추가하거나 재정의하여 새로운 클래스를 정의
  • 상위(부모) 클래스의 멤버를 하위(자식) 클래스에 그대로 내려주는 것

상속이 필요한 이유

  1. 중복되는 멤버 변수 / 메서드 재작성이 불필요
  2. 클래스의 재사용성과 유지 보수성 향상(여러 클래스에 포함되는 내용을 한번 정의하면, 각 클래스마다 상속의 형태로 재사용 가능, 시간, 비용 절감)
  3. 클래스 간의 계층 관계 → 가독성 향상 및 다형성을 구현 가능

상속 구현하기 - extends

class Person {...} //부모 클래스
class Programmer extends Person {...} //자식 클래스
  • extends 키워드를 이용해 클래스 상속
  • 멤버를 상속하는 기존 클래스 = 부모(상위 클래스), 상속을 받는 클래스 = 자식(하위 클래스)
  • 부모 클래스 Person과 자식 클래스 Programmer는 포함관계

메서드 오버라이딩(Method Overriding)

  • 상속받은 부모 클래스의 메서드를 자식 클래스에서 동일한 메서드 시그니처로 재정의하는 것
  • 같은 메서드 시그니처를 가진 동작을 자식 클래스에 맞게 수정 가능 → 새로운 메서드 선언 불필요

메서드 오버라이딩 조건

  1. 메서드 시그니처가 부모 클래스의 메서드와 동일
    • 메서드명과 매개변수의 자료형, 개수가 동일
  2. 메서드의 접근 제어자는 부모 클래스의 메서드와 같거나 더 넓은 범위이어야 함 → 추후 학습
  3. 메서드의 반환 자료형은 부모 클래스의 메서드와 같거나 하위 자료형이어야 함

메서드 오버라이딩 vs 메서드 오버로딩

  • 오버로딩은 한 클래스 내에서 이름이 동일하고 메서드 시그니처가 다른 여러 개의 메서드를 정의하는 것
  • 오버라이딩은 자식 클래스에서 부모 클래스의 메서드를 동일한 메서드 시그니처로 재정의 하는 것

super 키워드

  • super 키워드를 사용하면 부모 클래스로부터 상속받은 멤버 변수, 메서드 참조 가능
  • Super는 상속받은 멤버 변수, 메서드를 참조하기 때문에, 자식 클래스에서 위와 같이 동일한 이름의 멤버 변수가 선언 및 대입 되었다면 this.name과 super.name이 다를 수 있음

super() 메서드

  • super()는 부모 클래스의 생성자를 호출하는 메서드
  • 사용 방법
    1. super()는 항상 생성자의 첫 줄에 작성
    2. 이때 호출된 메서드 시그니처에 맞는 부모 클래스의 생성자가 호출됨
    3. super() 호출 이후에 필요하다면 추가적인 초기화 작업을 수행

캡슐화

  • 외부로부터 클래스에 정의된 상태와 동작을 보호 → 데이터 보호
  • 필요한 데이터만 외부 노출 → 데이터 은닉
  • 핵심 구현 방법 → 접근제어자와 getter/setter 메서드

접근 제어자의 필요성

  • 외부에서 객체가 가진 정보를 접근 / 변경할 수 있다면 의도하지 않은 값으로 조작될 위험이 있음
    ⇒ 데이터 보호와 데이터 은닉 필요
  • 상황에 맞게 멤버 변수와 메서드에 대해 적절한 접근 제어자를 정의해야 함

접근 제어자

getter/setter

  • getter 메서드는 멤버 변수를 반환해주는 메서드이다.
  • 직접 접근하는 것이 아닌, getter 메서드를 통해 멤버 변수 값을 읽을 수 있다.
  • setter 메서드는 멤버 변수를 변경하는 메서드이다.
  • 직접 변경하는 것이 아닌, setter 메서드를 통해 멤버 변수의 값을 변경한다.
  • getter와 setter 메서드 → 메서드를 거쳐야만 멤버 변수에 접근할 수 있도록 제어하고, 검증 절차를 통해 유효한 데이터만 저장할 수 있도록 설계 가능 ⇒ 데이터 보호
  • 외부에 노출이 불필요한 데이터를 숨겨 보다 가독성 있고 유지 보수에 용이한 코드 작성이 가능 ⇒ 데이터 은닉

    캡슐화를 통해 객체가 가진 데이터의 무결성을 보장할 수 있으며, 객체의 멤버가 정해진 규칙에 따라 유지될 수 있도록 설계하는 것이 중요하다.