phpclass/객체모델2005. 10. 11. 12:13
written: Oct 06 2005
last modified: Oct 11 2005
 
앞 문서들에서 접근제한자를 이용하여 가시범위(visibility) 지정하는 방법에 대하여 알아보았습니다. 이번 문서에서는 범위 지정 연산자(scope resolution operator;범위지정자)를 이용하여 유효범위(scope)를 지정하는 방법에 대하여 살펴보겠습니다.
유효범위(scope)
유효범위라는 것은 하나의 멤버를 기준으로 그 멤버에 접근할 수 있는 프로그램 영역을 나타내는 것으로 만일 프로그램의 모든 곳에서 접근할 수 있는 멤버라면 그 멤버의 유효범위는 프로그램 전체가 됩니다. 모든 멤버(변수, 함수, 상수)의 유효범위(scope)는 그 멤버가 정의되어 있는 프로그램의 위치에 따라 결정됩니다.
zend 1.0과 2.0의 유효범위에 관한 자세한 내용은  "상단메뉴 >> 클래스&객체 > Zend엔진 2.0 설계초안 > 이름공간(namespace)"를 참조바랍니다.
위 문서에 따르면 Zend 엔진에서는 아래와 같이 3가지의 유효범위를 제공하는 것으로 보입니다.
  • 전역 스코프(golbal scope)
  • 함수 스코프(function scope)
  • 클래스 스코프(class scope)
본 문서에서는 유효범위를 구분할 때에는 유효범위라는 용어보다는 스코프라는 용어를 직접 사용하여 가능한한 용어 사용상 혼동이 없도록 하겠습니다.
위에서 구분된 함수 스코프(function scope)라는 용어를 C++과 같은 언어에서는 지역 스코프(local scope)라고 부르고 있으며 함수 스코프는 다른 뜻으로 사용하고 있으니 양쪽 언어를 넘나드는 분들은 혼동없기를 바랍니다.
참고로 C++에서는 지역 스코프를 아래와 같이 설명하고 있습니다.
함수 또는 함수에 있는 어떤 블록(block) 안에서 정의되어 있는 모든 변수들은 지역 스코프를 가진다.
PHP에서는 블록 안에서만 사용할 수 있는 변수를 허용하지 않고 다만 함수 내에서 사용할 수 있는 변수를 허용하고 있습니다.
클래스 스코프(class scope)
Zend 엔진 2.0 알파2가 발표되면서 클래스 스코프와 관련하여 큰 변화는 중첩클래스(nested class;내부클래스)를 허용한다는 것과 import 문의 도입이었을 것입니다만 PHP5.0.0b1 이후 현재버전(5.0.4)에서는 둘 다 삭제되어 있습니다. 클래스 스코프에 포함될 수 있는 멤버를 보면 아래와 같습니다.
< 클래스 스코프 (o:포함허용, x:포함불가) >

\

Zend 엔진 버전

------------------

 멤버

\

1.0 2.0 알파2

2.0

상수

X

O

O

변수

O

O

O

함수

O

O

O

클래스

X

O

X

범위 지정 연산자(::)
앞에서 모든 멤버는 그 멤버가 정의된 프로그램 위치에 따라 그 멤버의 유효범위가 결정된다고 하였습니다. 그런데 때로는 자신이 속한 유효범위를 명시적으로 지정하여 사용할 수도 있습니다. 이러한 목적으로 범위 지정 연산자(scope resolution operator;범위지정자)를 사용합니다.
범위 지정 연산자를 이용하면 부모클래스 내에 있는 재정의되기 전의 멤버 또는 아직 인스턴스를 갖고 있지 않는 클래스 멤버에 접근할 수 있습니다.
클래스 밖에서 클래스 멤버 접근하기
클래스 밖에서 클래스 멤버에 접근하기 위해서는 "클래스명::멤버"와 같이 지정합니다.
상수(constant)
[code php;gutter:false] <?php class my_class { const MY_CONST = 'A constant value.'; } print my_class::MY_CONST . "\n"; ?> [/code]
< 상수에 접근하기 >
위 소스를 실행하면 "A constant value.\n"를 출력할 것입니다.
변수(variable)
[code php;gutter:false] <?php class my_class { public static $public_var = "my_class::public_var"; } print my_class::$public_var . "\n"; ?> [/code]
< 변수에 접근하기 >
위 소스를 실행하면 "my_class::public_var\n"를 출력할 것입니다.
함수(function)
[code php;gutter:false] <?php class my_class { public function my_function() { print "my_class::my_function()\n"; } } class my_class2 extends my_class { public function my_function() { my_class::my_function(); print "my_class2::my_function()\n"; } } /** * This will print * my_class::my_function() */ my_class::my_function(); /** * This will print * my_class::my_function() * my_class2::my_function() */ ?> [/code]
< 함수에 접근하기 >
클래스 안에서 클래스 멤버 접근하기
클래스 안에서 클래스 멤버에 접근할 때는  "클래스명::멤버"와 같이 지정할 수도 있으나 PHP4부터 제공되기 시작한 self와 parent 접근자를 이용하여 자신의 클래스나 상위 클래스의 멤버에 접근하는 것이 더 바람직합니다.
상수(constant)
[code php;gutter:false] <?php class my_class { const MY_CONST = "my_class::MY_CONST\n"; protected function my_function() { print self::MY_CONST; } } class my_class2 extends my_class { const MY_CONST = "my_class2::MY_CONST\n"; public function my_function() { print parent::MY_CONST; print self::MY_CONST; } } /** * This will print * my_class::MY_CONST */ my_class::my_function(); /** * This will print * my_class::MY_CONST * my_class2::MY_CONST */ my_class2::my_function(); ?> [/code]
< 상수에 접근하기 >
변수(variable)
[code php;gutter:false] <?php class my_class { public static $protected_var1 = "my_class::protected_var1\n"; public function my_function() { print self::$protected_var1; } } class my_class2 extends my_class { protected static $protected_var2 = "my_class2::protected_var2\n"; public function my_function() { print parent::$protected_var1; print self::$protected_var2; } } /** * This will print * my_class::protected_var1 */ my_class::my_function(); /** * This will print * my_class::protected_var1 * my_class2::protected_var2 */ my_class2::my_function(); ?> [/code]
< 변수에 접근하기 >
(에러수정) 예제가 잘못 코딩되어 에러가 발생하여 예제를 수정하였습니다.
함수(function)
[code php;gutter:false] <?php class my_class { protected function my_function() { print "my_class::my_function()\n"; } } class my_class2 extends my_class { protected function my_function() { print "my_class2::my_function()\n"; } public function public_func() { print parent::my_function(); print self::my_function(); } } my_class2::public_func(); ?> [/code]
< 함수에 접근하기 >
위 소스를 실행하면 아래와 같은 결과를 얻을 수 있습니다.
my_class's my_function()
my_class2's my_function()
심볼테이블
"상단메뉴 >> 클래스&객체 > Zend엔진 2.0 설계초안 > 이름공간(namespace)"를 보게되면 Zend엔진 각 버전별로 클래스의 심볼(상수명, 변수명, 함수명, 클래스명 등)에 대한 기본적인 유효범위가 상이합니다.
[code php;gutter:true] <?php function bar() { print "global's bar()\n"; } class my_class { function my_function() { bar(); } function bar() { print "myclass::bar()\n"; } } ?> [/code]
< 함수의 유효범위 >
위의 예에서 8번행의 bar()가 실행되었을 때 Zend 엔진 1.0에서는 전역 스코프(global scope)를 가지게 되어 전역함수 bar()를 호출하게 되며 결과는 "global's bar()\n"를 출력할 것입니다. 그러나 Zend 엔진 2.0 알파2에서는 8번행의 bar()가 실행되었을 때 bar() 문이 클래스 스코프(class scope)를 가지게 되어 클래스 메쏘드인 bar()를 호출하게 되며 결과는 "myclass::bar()\n"를 출력할 것입니다.
그런데 PHP5.0이 정식으로 발표되면서 포함된 Zend 엔진 2.0에서는 원래대로 클래스 스코프가 아니라 전역 스코프를 가지도록 수정되었습니다.
< 8번행 bar()문의 유효범위 >

\

Zend 엔진 버전

------------------

 유효범위

\

1.0 2.0 알파2

2.0

전역 스코프

O

X

O

클래스 스코프

X

O

X

main 접근자
Zend 엔진 2.0 알파2에서 제공되던 범위 접근자인 main이 PHP5.0.0b1이 발표되면서 삭제되었습니다. 그 이유는 앞 항목인 "심볼테이블"에서 살펴보았지만  bar()문을 실행하였을 때 Zend 엔진 2.0 알파2에서는 클래스 my_class에 정의된 bar() 메쏘드를 호출하게 됩니다. 그러면 Zend 엔진 2.0 알파2에서 전역함수 bar() 함수를 호출하려면 어떻게 해야 하나요? 이럴 때를 위하여 제공하였던 것이 main 접근자입니다. main 접근자로 임의 지정된 멤버는 현재 위치에 관계없이 전역영역에 있는 멤버를 호출하도록 해줍니다.
main::bar();
PHP5.0.0b1 이후에 포함된 Zend 엔진 2.0에서는 bar()문을 실행하였을 때 Zend 엔진 1.0과 같이 클래스 메쏘드가 아닌 전역함수를 호출하도록 변경되었기 때문에 main 접근자가 필요없어졌습니다. 이러한 이유로 Zend 엔진 2.0에서는 main 접근자가 삭제되었습니다.

Posted by 방글24