가시성 – 2.PPP 접근제한자

PPP 접근제한자(PPP visibility modifier)

프로퍼티, 메소드 또는 (PHP 7.1.0부터) 상수를 선언할 때 그 앞에 접근제한자(visibility modifier; access modifier) public, protected 또는 private 키워드를 붙임으로 가시성(visibility)를 정의할 수 있습니다.

(참고) 전역 변수, 지역 변수, 함수와 클래스는 접근제한자를 지정할 수 없습니다.

캡슐화된 클래스의 멤버(상수, 프로퍼티, 메소드)는 변화무쌍한 소프트웨어 현실 세계의 환경 속에서 개발생산성(SW development productivity)을 높이기 위해서, 다른 어떤 프로그램의 내용이 변경되더라도 자신의 프로그램은 전혀 영향을 받지 않도록 독립성(independency)을 확보해야 하며, 독립성을 확보함으로 자신의 프로그램을 이용하는 다른 프로그램들에게는 전혀 영향을 미치지 않으면서 변해가는 주변 환경에 적절히 대응할 수 있도록 자신의 프로그램을 개선할 수 있습니다.

이러한 소프트웨어의 독립성을 얻기 위한 하나의 방편으로써 정보 은닉(information hiding; data hiding) 개념을 도입하였으며, 정보 은닉 개념을 구현하기 위한 도구로 접근제한자(visibility modifier; access modifier)를 사용하고 있습니다.

접근제한자를 사용함으로 구체적인 클래스 내부 구조는 외부에 있는 프로그램에 공개하지 않고 단지 데이터를 조작하여 정보를 반환하여 주는 인터페이스(public 메소드)를 공개함으로, 인터페이스(public 메소드)를 통해서만 데이터를 조작하도록 제한하게 됩니다.

따라서 소프트웨어 독립성을 위한 정보 은닉 개념을 제대로 구현하려면 클래스 내부의 대부분의 멤버는 private 접근제한자로 지정하며, 클래스 외부에 공개할 일부 메소드(setter, getter 등)만 public 접근제한자로 공개하여야 합니다.

public 접근제한자(public access modifier)

public으로 선언된 클래스 멤버는 객체 외부에서 제한 없이 접근하여 데이터를 조작할 수 있습니다. 이에 따라 public 멤버는 소프트웨어의 독립성을 깨뜨려 프로그램의 유지보수를 어렵게 할 수 있으며, 또한 데이터 값에 대한 유효성을 보장할 수 없게 만듭니다.

예를 들어, 사람의 나이(age)를 기록하는 클래스를 작성할 때, 아래와 같이 멤버의 접근제한자를 public로 지정하게 되면, 해당 클래스 외부에서 멤버 데이터를 임의로 변경할 수 있게 되고, 이로 인해 고의 또는 실수로 변수 $age 값에 유효하지 않는 값이 저장될 수 있습니다.

$age는 나이를 의미하며 이 값은 음수로 표시될 수 없음에도 클래스 외부 프로그램에 의해 –2로 저장된 후 표시되고 있습니다. 이와 같이 클래스 프로퍼티를 클래스 외부에서 직접 접근하게 되면 멤버 데이터 값의 유효성, 즉 올바른 값이 사용되고 있는지 확인할 수 없게 됩니다.

이러한 문제는 명백히 잘못된 상황으로, 독립성을 유지해야 하는 캡슐화된 클래스 내에서는 반드시 예방해야 할 문제입니다. 이러한 문제를 예방하기 위해서는 클래스 프로퍼티에 public 접근을 허용해서는 안되며, 프로퍼티의 값은 반드시 유효성 검사를 포함된 public 메소드를 통해서 저장하고(setter) 저장된 값을 읽어오도록(getter) 해야 합니다.

이와 같이 유효성 검사가 내포된 메소드를 통해 프로퍼티에 접근하게 되면, 클래스의 독립성을 적절히 유지할 수 있게 되며, 변화하는 주변 상황에 적절히 대응하면서 클래스 내부의 코드를 외부 상황과 관계없이 개선할 수 있으며, 유지보수성(maintainability)을 향상시켜 개발생산성(development productivity)을 높일 수 있게 됩니다.

protected 접근제한자(protected access modifier)

protected로 선언된 멤버는 해당 클래스와 해당 클래스의 자식 또는 부모 클래스에서만 액세스 할 수 있습니다. protected로 선언된 멤버와 상속 관계에 있는 자식 클래스에서는 아무런 제약 없이 해당 멤버에 접근할 수 있도록 할 때 사용됩니다. 그러나 자식 클래스에 한정되기는 하지만 아무런 제약 없이 접근할 수 있다는 문제에 의해 public으로 선언했을 때의 유효성 문제가 다시 제기될 수 있습니다.

$sex는 성별을 의미하며 남성은 1, 여성은 2로 표시됨에도 불구하고 남성도 아니고 여성도 아닌 3이라는 값이 자식 클래스의 생성자에 의해 저장되었고 getter(getSex())에 의해 반환되어 표시되고 있습니다. 이와 같이 클래스 프로퍼티를 클래스 외부에서(위 예에서는 자식 클레스에서) 직접 접근하게 되면 멤버 데이터 값의 유효성, 즉 올바른 값이 할당되는지 확인할 수 없게 됩니다.

protected로 지정된 멤버를 가진 클래스로부터 상속된 자식 클래스가 그 부모의 protected 멤버를 직접 접근하기 때문에 부모와 자식 클래스 간의 의존성이 강하여 각각의 클래스를 독립성을 유지하며 프로그래밍하는 것이 거의 불가능합니다. 따라서 이와 같이 protected 멤버로 묶인 부모와 자식 클래스는 하나의 패키지로 묶어서 유지 관리되어야 하는 어려움이 있습니다. 이와 같은 이유로 패키지화하여 유지 관리할 수 있는 경우와 같은 특별한 경우에만 protected 접근제한자를 사용해야 할 것으로 보이며, 그 외에는 모두 private 접근제한자를 이용하여 소프트웨어의 독립성을 확보하는 것이 중요합니다.

위와 같이 protected 멤버로 묶인 부모 클래스 Person과 자식 클래스 Man, Woman 클래스는 하나의 패키지로서 프로그래밍 되고 유지 관리되는 것이 바람직합니다.

private 접근제한자(private access modifier)

private으로 선언된 멤버는 해당 멤버를 정의한 클래스 내에서만 접근할 수 있으므로, 클래스 외부에서는 접근이 불가능하며, 하위 클래스에서도 접근이 불가능합니다.

소프트웨어의 독립성을 확보하기 위해서는 클래스의 정보 중에서 필요한 멤버만 클래스 외부에 있는 프로그램이 접근할 수 있도록 하고, 나머지 멤버는 모두 private(특별한 경우에만 protected)로 지정하여 외부에서 접근할 수 없도록 하여야 합니다.

PHP에서 명시적으로 접근제한자을 지정하지 않고 선언된 상수와 메소드, var로 선언된 프로퍼티는 public으로 정의되는 반면에 C++에서는 private로 처리됩니다. 자바의 경우에는 private와 protected의 중간쯤 되는 default 접근제한자가 있어서 별도로 접근제한자를 지정하지 않는다면 default로 설정됩니다.

답글 남기기