Menu
Coddy logo textTech

접근 제어자 심화

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

이제 세 가지 접근 제어자를 이해했으므로, 상속 시나리오에서 이들이 어떻게 동작하는지 살펴보겠습니다. 핵심은 protected 멤버는 자식 클래스에서 접근 가능해지지만, private 멤버는 자식 클래스에게도 숨겨진 상태로 유지된다는 점입니다.

<?php
class Vehicle {
    public $brand;
    protected $engineType;
    private $serialNumber;
    
    public function __construct($brand, $engine, $serial) {
        $this->brand = $brand;
        $this->engineType = $engine;
        $this->serialNumber = $serial;
    }
    
    private function getSerial() {
        return $this->serialNumber;
    }
    
    protected function getEngineInfo() {
        return $this->engineType;
    }
}

class Car extends Vehicle {
    public function getDetails() {
        return $this->brand . " - " . $this->getEngineInfo();
        // $this->serialNumber는 오류를 발생시킵니다 - private!
        // $this->getSerial() 또한 실패합니다 - private 메서드!
    }
}

$car = new Car("Toyota", "V6", "ABC123");
echo $car->getDetails();

출력:

Toyota - V6

Car 클래스는 $brand (public)에 접근할 수 있고 getEngineInfo() (protected)를 호출할 수 있지만, $serialNumbergetSerial()에는 접근할 수 없습니다. 왜냐하면 이들은 Vehicle에 private으로 설정되어 있기 때문입니다. 이러한 구분은 일부 내부 세부 사항을 자식 클래스와 공유하면서도 다른 부분은 완전히 숨길 수 있게 해줍니다.

핵심 포인트: 자식 클래스가 내부 데이터나 메서드에 접근해야 할 때는 protected를 사용하고, 자식 클래스조차 특정 구현 세부 사항을 건드리지 않아야 할 때는 private를 사용하세요.

challenge icon

챌린지

쉬움

상속 관계에서 접근 제어자(access modifiers)가 어떻게 동작하는지 탐구하는 장치 관리 시스템을 구축해 보겠습니다. 서로 다른 가시성 수준을 가진 속성을 포함하는 기본 Device 클래스를 만들고, 이를 확장한 Smartphone 클래스를 통해 자식 클래스가 어떤 멤버에 접근할 수 있고 없는지 확인해 봅니다.

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

  • Device.php — 데이터 민감도가 다양한 전자 장치를 나타내는 Device 클래스를 생성합니다. 다음을 포함하세요:
    • 제조사 이름을 위한 public 속성 $brand
    • 내부 식별을 위한 protected 속인 $modelNumber
    • 공장 전용 데이터를 위한 private 속성 $manufacturingCode
    생성자는 이 세 가지 값을 모두 받아야 합니다. 제조 코드를 반환하는 private 메서드 getManufacturingCode()를 추가하세요. "Model: [modelNumber]"를 반환하는 public 메서드 getModelInfo()를 추가하세요. 마지막으로 "[brand]-[manufacturingCode]"를 반환하는 public 메서드 getFullCode()를 추가하세요. 이는 클래스 자체가 자신의 private 멤버에 어떻게 접근할 수 있는지 보여줍니다.
  • Smartphone.phpDevice를 상속받는 Smartphone 클래스를 생성합니다. Device 파일을 포함(include)하세요. 생성자는 brand, modelNumber, manufacturingCode, 그리고 운영체제(OS) 이름을 받아야 합니다. 처음 세 개의 값으로 부모 생성자를 호출한 다음, OS를 private 속성에 저장하세요. "[brand] [modelNumber] running [os]"를 반환하는 public 메서드 getDeviceDetails()를 추가하세요. 여기서 public인 $brand와 protected인 $modelNumber에는 직접 접근할 수 있지만, private인 $manufacturingCode에는 직접 접근할 수 없다는 점에 유의하세요. 대신 상속받은 public 메서드인 getFullCode()를 사용해야 합니다.
  • main.php — Smartphone 파일을 포함하세요. 브랜드 이름, 모델 번호, 제조 코드, 운영체제라는 네 가지 입력을 받게 됩니다. 이 값들로 Smartphone 인스턴스를 생성하세요. 다음 세 줄을 출력합니다:
    • getDeviceDetails() 호출 결과
    • 상속받은 getModelInfo() 메서드 호출 결과
    • 상속받은 getFullCode() 메서드 호출 결과

이 챌린지는 핵심적인 차이점을 강조합니다. Smartphone 클래스는 Device로부터 상속받은 protected $modelNumber를 자유롭게 사용할 수 있지만, private $manufacturingCodegetManufacturingCode()는 완전히 숨겨진 상태로 유지되며 Device가 노출하기로 선택한 public 인터페이스를 통해서만 접근할 수 있습니다.

치트 시트

상속에서 protected 멤버는 자식 클래스에서 접근할 수 있지만, private 멤버는 자식 클래스에게도 숨겨진 상태로 유지됩니다.

<?php
class Vehicle {
    public $brand;
    protected $engineType;
    private $serialNumber;
    
    public function __construct($brand, $engine, $serial) {
        $this->brand = $brand;
        $this->engineType = $engine;
        $this->serialNumber = $serial;
    }
    
    private function getSerial() {
        return $this->serialNumber;
    }
    
    protected function getEngineInfo() {
        return $this->engineType;
    }
}

class Car extends Vehicle {
    public function getDetails() {
        return $this->brand . " - " . $this->getEngineInfo();
        // $this->serialNumber would cause an error - private!
        // $this->getSerial() would also fail - private method!
    }
}

$car = new Car("Toyota", "V6", "ABC123");
echo $car->getDetails(); // Toyota - V6

자식 클래스가 접근할 수 있는 항목:

  • public 속성과 메서드
  • protected 속성과 메서드

자식 클래스가 접근할 수 없는 항목:

  • private 속성과 메서드 (이들은 부모 클래스 전용으로 유지됩니다)

권장 사항: 자식 클래스가 내부 데이터나 메서드에 접근해야 할 때는 protected를 사용하고, 자식 클래스조차 특정 구현 세부 사항을 건드리지 않아야 할 때는 private를 사용하세요.

직접 해보기

<?php
require_once 'Smartphone.php';

// 입력 읽기
$brand = trim(fgets(STDIN));
$modelNumber = trim(fgets(STDIN));
$manufacturingCode = trim(fgets(STDIN));
$os = trim(fgets(STDIN));

// TODO: 입력된 값으로 Smartphone 인스턴스 생성

// TODO: getDeviceDetails()의 결과 출력

// TODO: 상속된 getModelInfo() 메서드의 결과 출력

// TODO: 상속된 getFullCode() 메서드의 결과 출력
?>
quiz icon실력 점검

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

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