접근 제어자 심층 이해
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 - V6Car 클래스는 $brand(public)에 액세스하고 getEngineInfo()(protected)를 호출할 수 있지만, $serialNumber 또는 getSerial()에는 액세스할 수 없습니다. 이러한 항목은 Vehicle에 private이기 때문입니다. 이러한 구분을 통해 일부 내부 세부 정보를 자식 클래스와 공유하면서 다른 정보는 완전히 숨길 수 있습니다.
핵심 요점: 자식 클래스가 내부 데이터나 메서드에 액세스해야 할 때는 protected를 사용하고, 자식 클래스조차 특정 구현 세부 사항에 접근해서는 안 될 때는 private를 사용하세요.
챌린지
쉬움상속 전반에서 access modifiers가 어떻게 동작하는지 살펴보는 device management system을 만들어 보겠습니다. 다양한 visibility level의 properties를 가진 기본 Device class를 만든 다음, 자식 class가 어떤 members에 access할 수 있고 cannot access하는지 보여 주는 Smartphone class로 확장합니다.
코드를 세 개의 파일로 구성합니다.
Device.php: 다양한 수준의 data sensitivity를 가진 electronic devices를 나타내는Deviceclass를 만듭니다. 다음을 포함합니다.- manufacturer name을 위한
publicproperty$brand - internal identification을 위한
protectedproperty$modelNumber - factory-only data를 위한
privateproperty$manufacturingCode
privatemethodgetManufacturingCode()를 추가합니다."Model: [modelNumber]"를 반환하는publicmethodgetModelInfo()를 추가합니다. 마지막으로"[brand]-[manufacturingCode]"를 반환하는publicmethodgetFullCode()를 추가합니다. 이를 통해 class 자체가 자신의 private members에 access할 수 있음을 보여 줍니다.- manufacturer name을 위한
Smartphone.php:Device를 extends하는Smartphoneclass를 만듭니다. Device file을 포함합니다. constructor는 brand, modelNumber, manufacturingCode, operating system name을 받아야 합니다. 처음 세 값을 사용해 parent constructor를 Call한 다음, OS를 private property에 저장합니다."[brand] [modelNumber] running [os]"를 반환하는 public methodgetDeviceDetails()를 추가합니다. public$brand에는 directly access할 수 있고 protected$modelNumber에도 access할 수 있지만, private$manufacturingCode에는 directly access할 수 없다는 점에 주목하세요. 대신 inherited public methodgetFullCode()를 사용해야 합니다.main.php: Smartphone file을 포함합니다. 네 개의 inputs, 즉 brand name, model number, manufacturing code, operating system을 받습니다. 이 값들로Smartphoneinstance를 Create합니다. 세 줄을 Print합니다.getDeviceDetails()를 Call한 결과- inherited
getModelInfo()method를 Call한 결과 - inherited
getFullCode()method를 Call한 결과
이 challenge는 핵심적인 차이를 강조합니다. Smartphone class는 Device에서 inherited된 protected $modelNumber를 자유롭게 사용할 수 있지만, private $manufacturingCode와 getManufacturingCode()는 완전히 hidden 상태로 남아 있습니다. 즉, Device가 노출하도록 선택한 public interface를 통해서만 access할 수 있습니다.
직접 해보기
<?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() 메서드의 결과 출력
?>이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.
객체 지향 프로그래밍의 모든 레슨
직접 연습해 보세요: 온라인 PHP 컴파일러