Computer >> 컴퓨터 >  >> 프로그래밍 >> PHP

PHP 가시성(접근 제어자) 완벽 정리: public, private, protected 차이와 활용법


개요

PHP에서는 class 키워드를 사용해 사용자 정의 복합 데이터 타입을 만들 수 있습니다. 클래스의 새 인스턴스가 곧 객체(object)이며, 객체의 특성은 해당 클래스의 정의를 따릅니다. 클래스에는 프로퍼티(property), 상수(constant), 메서드(method) 같은 멤버들이 포함될 수 있습니다.

클래스 멤버의 접근 범위를 가리켜 '가시성(visibility)'이라 하며, 멤버를 정의할 때 붙이는 가시성 키워드에 따라 결정됩니다. PHP는 다음 세 가지 가시성 키워드를 제공합니다.

  • public: 어디에서든 접근할 수 있습니다.
  • protected: 해당 클래스 내부와 이를 상속한 자식 클래스에서만 접근할 수 있습니다.
  • private: 정의된 클래스 내부에서만 접근할 수 있으며, 외부에는 완전히 숨겨집니다.

프로퍼티 가시성

프로퍼티는 클래스 인스턴스의 속성으로, 객체마다 서로 다른 값을 갖는 인스턴스 프로퍼티와 모든 객체가 동일한 값을 공유하는 클래스 프로퍼티로 나뉩니다. 프로퍼티는 유효한 PHP 데이터 타입이면 어떤 것이든 사용할 수 있으며, 별도의 키워드를 지정하지 않으면 기본적으로 public 가시성을 갖습니다. 참고로 이미 폐기(deprecated)된 var 키워드로 선언된 프로퍼티도 public으로 취급됩니다.

예제 1: 클래스 외부에서 프로퍼티 접근

<?php
class myclass{
    public $fname="Ajay";
    var $lname; // public으로 취급됨
    private $marks=100;
    protected $age=20;
}
$obj=new myclass();
echo "$obj->fname
";
$obj->lname="Diwan";
echo "$obj->marks
";
$obj->age=21;
?>

실행 결과

아래 결과에서 알 수 있듯이 public 프로퍼티는 클래스 외부에서 자유롭게 접근할 수 있지만, private 또는 protected 프로퍼티에 접근하면 치명적 오류(fatal error)가 발생합니다.

Ajay
PHP Fatal error: Uncaught Error: Cannot access private property myclass::$marks
PHP Fatal error: Uncaught Error: Cannot access protected property myclass::$age

반면 private와 protected 프로퍼티는 같은 클래스 내부의 메서드 안에서는 자유롭게 사용할 수 있습니다.

예제 2: 클래스 내부에서 프로퍼티 접근

<?php
class myclass{
    public $fname="Ajay";
    var $lname;
    private $marks=100;
    protected $age=20;
    function displaydata(){
        $this->lname="Diwan";
        echo "$this->fname $this->lname
";
        echo "marks=$this->marks age=$this->age";
    }
}
$obj=new myclass();
$obj->displaydata();
?>

실행 결과

Ajay Diwan
marks=100 age=20

메서드 가시성

클래스 프로퍼티와 마찬가지로 메서드에도 public, private, protected 키워드로 가시성을 지정할 수 있으며, 기본값은 public입니다.

예제 3: 메서드 가시성 확인

<?php
class myclass{
    public $fname="Ajay";
    var $lname;
    private $marks=100;
    protected $age=20;
    public function setname(){
        $this->fname="Anil";
        $this->lname="Dave";
        echo "name changed
";
    }
    private function setmarks(){
        $this->marks=90;
    }
    protected function setage(){
        $this->age=21;
    }
    function setdata(){
        $this->setname();
        $this->setmarks();
        $this->setage();
    }
    function displaydata(){
        $this->lname="Diwan";
        echo "$this->fname $this->lname
";
        echo "marks=$this->marks age=$this->age";
    }
}
$obj=new myclass();
$obj->setname(); // 정상 실행
$obj->setmarks(); // 오류 발생
$obj->setage(); // 오류 발생
$obj->setdata(); // public 메서드 내부에서 private/protected 메서드 호출
$obj->displaydata();
?>

실행 결과

외부에서 private·protected 메서드를 직접 호출하면 오류가 발생하지만, 같은 클래스 내부의 public 메서드(setdata())를 통해 호출하면 정상적으로 실행됩니다.

name changed
PHP Fatal error: Uncaught Error: Call to private method myclass::setmarks() from context ''
PHP Fatal error: Uncaught Error: Call to protected method myclass::setage() from context ''
Anil Dave
marks=90 age=21

상속 관계에서의 메서드 가시성

부모(parent) 클래스의 메서드는 자식(child) 클래스에서 재정의(override)할 수 있습니다. 부모의 private 및 protected 메서드는 자식 클래스의 객체를 통해서는 호출할 수 없지만, 부모에서 protected로 선언된 메서드는 자식 클래스의 메서드 내부에서는 사용할 수 있습니다.

예제 4: 상속과 메서드 가시성

<?php
class testclass{
    public $x=10;
    private $y=20;
    protected $z=30;
    private function test(){
        echo "testclass private method
";
    }
    public function test1(){
        echo "testclass public method
";
    }
    protected function test2(){
        echo "testclass protected method
";
    }
    function test3(){
        echo "x=$this->x y=$this->y z=$this->z
";
    }
}
class newclass extends testclass{
    function test1(){
        echo "newclass public method
";
    }
    public function test4(){
        $this->test();
        $this->test1();
        $this->test2();
    }
}
$obj=new newclass();
echo $obj->test1();
echo $obj->test3();
echo $obj->test4();
?>

실행 결과

자식 클래스에서 부모의 private 메서드를 호출하려는 순간 오류가 발생합니다. 반면 public 메서드 재정의와 부모 프로퍼티 접근은 문제없이 동작합니다.

newclass public method
x=10 y=20 z=30
PHP Fatal error: Uncaught Error: Call to private method testclass::test() from context 'newclass'

상수 가시성

PHP 7.1부터는 클래스 상수에도 가시성 모드를 적용할 수 있습니다. 상수의 기본 가시성은 public입니다.

예제 5: 상수 가시성 확인

<?php
class testclass{
    public const X=10;
    private const Y=20;
    protected const Z=30;
    function showconst(){
        echo "x=" . self::X ;
        echo "y=" . self::Y;
        echo "z=" . self::Z ;
    }
}
$obj=new testclass();
$obj->showconst();
echo testclass::Y . "
";
echo testclass::Z . "
";
?>

실행 결과

클래스 내부에서는 모든 상수에 접근할 수 있지만, 외부에서 private·protected 상수에 접근하면 오류가 발생합니다.

x=10y=20z=30
PHP Fatal error: Uncaught Error: Cannot access private const testclass::Y
PHP Fatal error: Uncaught Error: Cannot access protected const testclass::Z

가시성별 접근 범위 정리

가시성같은 클래스 내부자식 클래스클래스 외부
public허용허용허용
protected허용허용불가
private허용불가불가

가시성 키워드를 적절히 활용하면 클래스 내부 구현을 외부로부터 보호하는 캡슐화(encapsulation)를 실현할 수 있으며, 이는 유지보수성과 코드 안정성을 높이는 객체지향 설계의 핵심 원칙입니다.