phpclass/객체정보2008. 8. 11. 12:37
작성: 2008.08.11
이름지정규칙(Name resolution rules)
네임스페이스 지원으로 이름(클래스명, 함수명 등)은 동일하지만 서로 다른 네임스페이스에 소속될 수 있기 때문에 각 이름이 소속된 네임스페이스를 명확히 지정할 필요가 있습니다. 이름을 지정하는 방법으로는 크게 4가지로 나눌 수 있습니다.
▶ 다른 네임스페이스에 있는 이름을 참조할 때는 Fully Qualified Name 사용
▶ 현재 네임스페이스에 있는 이름을 참조할 때는 Unqualified Name 사용
▶ use 연산자를 이용하여 다른 네임스페이스를 현재 네임스페이스로 가져옴(import)
▶ 전역 네임스페이스에 있는 이름을 참조할 때는 네임스페이스 이름없이 :: 연산자로 시작함
Fully Qualified Name은 네임스페이스의 완전한 이름으로 아래의 예에서 볼 때 MyProject::Connection::NS_CONST, MyProject::Connection::my_function을 의미합니다.
[code php;gutter:true] <?php namespace MyProject::Connection; const NS_CONST = 'namespace constant NS_CONST'; function my_function() { print "namespace function my_function()\n"; } print MyProject::Connection::NS_CONST . "\n"; MyProject::Connection::my_function(); ?> [/code]
다른 네임스페이스에 있는 이름을 참조할 때는 완전한 네임스페이스 이름을 가진 Fully Qualified Name을 사용하여야 하나 현재 네임스페이스에 있는 이름을 참조할 때는 네임스페이스 이름을 생략한 Unqualified Name을 사용할 수 있습니다. 위의 예에서 10, 11번행의 현재 네임스페이스가 MyProject::Connection이므로 아래와 같이 Fully Qualified Name 대신에 Unqualified Name을 사용할 수 있습니다.
[code php;gutter:false] print NS_CONST . "\n"; my_function(); [/code]
전역 네임스페이스(global namespace)는 그 이름을 가지고 있지 않으므로 네임스페이스 이름을 지정할 수 없습니다. 이런 이유로 전역 네임스페이스에 소속된 이름을 참조할 때는 네임스페이스 이름없이 :: 연산자로 시작하는 이름을 사용합니다.
[code php;gutter:false] <?php namespace A::B::C; /* This function is A::B::C::fopen */ function fopen() { /* ... */ $f = ::fopen(...); // call global fopen return $f; } ?> [/code]
use 연산자를 이용하면 스크립트 실행시 다른 네임스페이스를 현재 네임스페이스로 임포트할 수 있습니다. 따라서 소스를 작성하거나 보기에 불편한 긴 Fully Qualified Name 대신에 짧은 별명(alias)을 사용할 수 있습니다. PHP에서 벤치마킹한 것으로 보이는 C++에서는 짧은 이름을 사용하기 위한 방법으로 별명을 이용하는 것 말고도 using 지시자(directive)와 using 선언자(declaration)를 이용하는 방법이 있습니다만 PHP에서는 이러한 방법까지는 제공하지 않습니다.
[code php;gutter:false] <?php namespace MyProject::Connection; function my_class() { /* code */ } ?> [/code]
< inc.php >
[code php;gutter:false] <?php require_once('inc.php'); use MyProject::Connection as Connection; $my = new Connection::my_class(); ?> [/code]
Unqualified 함수 호출
네임스페이스 내에서 Unqualified 함수를 호출하면 아래와 같은 규칙에 따라 해당 함수를 호출합니다.
① 현재 네임스페이스에 정의된 함수를 호출
② PHP 내장(internal; built-in) 함수를 호출
[code php;gutter:true] <?php namespace A::B; $a = ucfirst("testing 'name resolution rules'"); echo($a); function ucfirst($str) { return '<span style="font-size:32pt;color:steelblue">' . ::ucfirst(substr($str, 0, 1)) . '</span>' . substr($str, 1); } ?> [/code]
위 소스의 4번행을 실행하면 7번행에 정의된 현재 네임스페이스의 ucfirst 함수를 호출합니다. 따라서 위 소스를 실행하면 아래와 같은 결과를 얻을 수 있습니다.
Testing 'name resolution rules'
만약 7번행부터 12번행에서와 같이 현재 네임스페이스에 정의된 ucfirst() 함수가 없었다면 PHP 내장함수인 ucfirst()를 바로 호출하였을 것이고 그 결과는 아래와 같았을 것입니다.
Testing 'name resolution rules'
Unqualified 클래스 호출
현재 네임스페이스가 A::B::C일 때, new C()는 A::B::C()로 변환됩니다. 현재 네임스페이스가 A::B일 때, new C()의 호출은 아래와 같은 규칙에 따릅니다.
① 네임스페이스 A::B 내에 정의된 클래스 C에 대한 객체 생성
② PHP 내장(internal; built-in) 클래스에 대한 객체 생성
Qualified 함수 호출
A::B::foo() 함수의 호출은 아래와 같은 규칙에 따릅니다.
① 네임스페이스 A::B 내에 정의된 함수 foo()를 호출
② 클래스 A::B의 정적 멤버 함수 foo()를 호출
[code php;gutter:false] <?php namespace A; // static methods/namespace functions of current namespace A::foo(); // first tries to call function "foo" from namespace "A::A" // then tries to call method "foo" of class "A" from namespace "A" // then tries to call function "foo" from namespace "A" // then calls method "foo" of internal class "A" ?> [/code]
< 출처:php.net >
Qualified 클래스 호출
new A::B::C()는 네임스페이스 A::B의 클래스 C를 참조합니다.
 

Posted by 방글24
phpclass/객체정보2008. 8. 9. 12:36
작성: 2008.08.09
네임스페이스 다루기
임의의 네임스페이스 내에 있는 모든 심볼(클래스명, 함수명, 변수명, 상수명 등)은 네임스페이스_식별자::심볼과 같은 식으로 다루어집니다.
namespaced_idenfitier::symbol;
[code php;gutter:false] <?php namespace MyProject::Connection; function my_class() { /* code */ } ?> [/code]
< inc.php >
[code php;gutter:false] <?php require_once('inc.php'); $my = new MyProject::Connection::my_class(); ?> [/code]
use 연산자(use operator)
use namespaced_name as othername;
use 연산자를 사용하면 원래 네임스페이스 이름 대신에 별명으로 임포트(import)할 수 있기 때문에 긴 이름 대신에 더 짧은 이름을 사용할 수 있어 문서를 단순화 시킬 수 있습니다. 짧은 이름의 othername은 스크립트 문서가 실행될 때 원래의 이름인 namespaced_name으로 변환됩니다.
위의 예제에서 보았듯이 use 연산자를 사용하지 않을 경우에는 MyProject::Connection::my_class()와 같은 전체 이름으로 참조해야 합니다. 그러나 use 연산자를 사용할 경우에는 아래와 같이 Connection::my_class()와 같이 더 짧은 이름을 사용할 수 있습니다.
[code php;gutter:false] <?php require_once('inc.php'); use MyProject::Connection as Connection; $my = new Connection::my_class(); ?> [/code]
또한 use MyProject::Connection as Connection; 에서 Connection과 같이 동일한 이름의 별명을 사용할 경우에는 아래와 같이 as 이하의 구문을 생략할 수 있습니다.
[code php;gutter:false] <?php require_once('inc.php'); use MyProject::Connection; $my = new Connection::my_class(); ?> [/code]
use 연산자는 전역 범위(global scopr)에서만 사용할 수 있으며 함수 또는 클래스 내에서는 사용할 수 없습니다. use 연산자에 의해 임포트된 이름은 임포트된 부분부터 현재 파일의 끝까지 영향을 미칩니다.
상수 __NAMESPACE__(constants __NAMESPACE__)
컴파일-타임 상수인 __NAMESPACE__ 에는 현재 네임스페이스 이름을 가지고 있습니다. 네임스페이스를 벗어나면 빈문자열(empty string)을 값으로 할당됩니다. 따라서 전역 네임스페이스(global namespace)에서 __NAMESPACE__의 값은 빈문자열입니다.
[code php;gutter:false] <?php namespace A::B::C; function foo() { // do stuff } set_error_handler(__NAMESPACE__ . "::foo"); ?> [/code]
< 출처:php.net >

Posted by 방글24
phpclass/객체정보2008. 8. 9. 12:35
작성: 2008.08.09
내장 네임스페이스
php v5.3 이전의 네임스페이스
php v5.3 이전에도 내장된 네임스페이스가 존재하고 있었습니다.
[code php;gutter:false] <?php $str = "전역 네임스페이스(global namespace)의 변수"; function test() { $str = "지역 네임스페이스(local namespace)의 변수"; print "$str<BR>\n"; global $str; print "$str<BR>\n"; } test(); ?> [/code]
test() 함수 내에서 동일한 변수이름 $str이 두 번 사용되고 있지만 하나는 지역 네임스페이스에서, 다른 하나는 전역 네임스페이스의 이름을 참조합니다. 따라서 이 소스를 실행하면 아래와 같이 나타날 것입니다.
전역 네임스페이스 - 함수(또는 클래스) 바깥쪽에서 정의된 이름
지역 네임스페이스 - 함수(또는 메소드) 안에서 정의된 이름 또는 클래스 안에서 정의된 이름
이와 같이 php v5.3 이전에도 내장된 네임스페이스가 존재하고 있어서 묵시적(implicit)으로 사용하여 왔으나, php v5.3 부터는 프로그래머가 새로운 네임스페이스를 직접 명시적(explicit)으로 정의하여 사용할 수 있도록 하였습니다.
전역 네임스페이스(Global namespace; Global space)
네임스페이스를 지원하는 php v5.3에서 네임스페이스가 정의되지않은 클래스 및 함수는 전역 네임스페이스에 존재합니다. 전역 네임스페이스는 특정한 이름(identifier)을 가지고 있지 않기 때문에 네임스페이스_식별자::함수명과 같은 식으로 호출할 수가 없으므로 이 때는 네임스페이스_식별자없이 범위지정자 ::로 시작되는, 즉 ::함수명과 같은 식으로 전역 네임스페이스에 존재하는 함수를 호출합니다.
[code php;gutter:false] <?php namespace A::B::C; /* This function is A::B::C::fopen */ function fopen() { /* ... */ $f = ::fopen(...); // call global fopen return $f; } ?> [/code]
< 출처:php.net >
 

Posted by 방글24
phpclass/객체정보2008. 8. 9. 12:34
작성: 2008.08.09
네임스페이스의 정의
이 문서에서 기술된 모든 소스는 2008년 8월 6일자 php-5.3.0 알파2 개발버전(php5.3-win32-200808062030.zip)으로 테스트하였습니다.
네임스페이스의 정의는 namespace 키워드에 이어 네임스페이스 식별자(identifier)를 지정합니다.
namespace identifier;
스크립트 문서 단위로 이루어지는 네임스페이스
C++과 같은 다른 언어와 달리 php v5.3에서 제공하는 이름공간 기능은 스크립트 문서 단위로 이루어진다는 것입니다. 그리고 네임스페이스의 지정은 다른 실행코드에 앞서 정의되어야 합니다. 그렇지 않고 네임스페이스를 정의하기 전에 다른 실행코드가 문서에 나타나면 아래와 같은 에러를 발생시킵니다.
Fatal error: Namespace declaration statement has to be the very first statement in the script in test.php on line xx
A_SPACE와 B_SPACE 네임스페이스 각각에 존재하는 동일한 이름의 함수 my_function()가 어떻게 동작하는지에 대한 간단한 예를 살펴보겠습니다.
[code php;gutter:false] <?php namespace A_SPACE; function my_function() { print "A_SPACE에서 정의한 함수\n"; } ?> [/code]
< inc1.php >
[code php;gutter:false] <?php namespace B_SPACE; function my_function() { print "B_SPACE에서 정의한 함수\n"; } ?> [/code]
< inc2.php >
[code php;gutter:false] <?php require_once('inc1.php'); require_once('inc2.php'); A_SPACE::my_function(); B_SPACE::my_function(); ?> [/code]
< test.php >
test.php를 실행하게 되면 아래와 같은 결과를 얻을 수 있습니다.
A_SPACE에서 정의한 함수
B_SPACE에서 정의한 함수
여러 개의 파일이 동일한 네임스페이스를 사용하는 예
동일한 명칭의 네임스페이스를 여러 파일에서 사용할 수 있기 때문에 동일한 네임스페이스 내에서 여러 파일로 나누어 작업할 수 있습니다.
[code php;gutter:false] <?php namespace MyProject::Connection; const NS_CONST = 'namespace constant NS_CONST'; class my_class { const MY_CONST = 'my_class::MY_CONST'; public static $public_var = "my_class::public_var"; public function my_function() { print "my_class::my_function()\n"; } } function my_function() { print "namespace function my_function()\n"; } ?> [/code]
< inc1.php >
[code php;gutter:false] <?php namespace MyProject::Connection; class my_class2 extends my_class { public function my_function() { my_class::my_function(); print "my_class2::my_function()\n"; } } ?> [/code]
< inc2.php >
[code php;gutter:false] <?php require_once('inc1.php'); require_once('inc2.php'); print MyProject::Connection::NS_CONST . "\n"; MyProject::Connection::my_function(); print MyProject::Connection::my_class2::MY_CONST . "\n"; print MyProject::Connection::my_class2::$public_var . "\n"; MyProject::Connection::my_class2::my_function(); ?> [/code]
< test.php >
test.php를 실행하게 되면 아래와 같은 결과를 얻을 수 있습니다.
[code php;gutter:false] namespace constant NS_CONST namespace function my_function() my_class::MY_CONST my_class::public_var my_class::my_function() my_class2::my_function() [/code]

Posted by 방글24
phpclass/객체정보2008. 8. 9. 12:32
작성: 2008.08.09
네임스페이스의 필요성
PHP로 프로그래밍할 때 보통 일인체제하에 소규모로 만들어지는 경우가 많다 보니 함수명, 클래스명과 같은 이름이 중복되어 충돌되는 것을 쉽게(?) 피할 수 있었습니다. 그러나 이제 PHP도 여러 사람이 공동 작업하는 경우도 많게 되고 제작되는 프로그램 덩치도 커지고 복잡해지다보니 이름의 중복으로 발생하는 충돌을 피하기가 쉽지 않게 되었습니다.
이러한 이유로 PHP의 미래 버전인 v6에서는 처음부터 네임스페이스를 지원하도록 설계/제작되고 있습니다. 이러한 와중에 그동안의 알려진 바와 같이 php v5.3에 네임스페이스 기능이 이식되어 2008년 8월 1일에 php 5.3 알파1 버전으로 정식으로 공개되었습니다.
객체지향언어 중에는 네임스페이스를 지원하지 않는 언어도 있는 이유로 혹자는 네임스페이스가 꼭 필요한 것이냐고 반문하는 분도 계시지만 네임스페이스가 객체화 도구가 아니고 모듈화 도구이기 때문에 객체지향언어와 무관하게 좀 더 개선된 모듈화 프로그래밍을 할 수 있는 좋은 도구라고 이해하면 될 것 같습니다.
사실 클래스를 이용하면 네임스페이스 지원없이도 함수명, 변수명, 상수명 등의 중복으로 발생하는 충돌을 잘 피할 수 있습니다. 그러나 클래스명의 경우는 그렇지 않습니다. PHP v5 버전이 공개되면서 새로 개발되는 거의 대부분의 PHP 코드들이 클래스를 이용하게 된 현실로 볼 때 모듈화 도구로서 자연스럽게 네임스페이스을 지원하게 된 것 같습니다.
"클래스를 사용해야하나?"라는 문서를 통해 모듈화에서 네임스페이스(namespace; 이름공간)의 역할에 대하여 설명드렸던 것처럼 갈수록 점점 복잡해지고 덩치가 커져가는 PHP 라이브러리와 같은 프로그램에서 함수명, 클래스명, 변수명 등의 이름 충돌 문제를 자주 접하게 됩니다. 그동안 대부분의 프로그래머들은 이러한 문제를 피하기 위하여 이름 앞에 해당 프로그램의 특징을 나타내는 접두어를 붙이는 방법을 주로 사용하여 왔으나 이러한 방법은 이름의 길이를 길게 만들기 때문에 소스를 복잡하게 만드는 등 좋지않은 요인으로 작용하였습니다.
예를 들어 후키템플릿 라이브러리에서 정의된 클래스명을 보면 아래와 같이 대부분의 클래스명에는 접두어로 hTemplate가 붙습니다. 이것은 다른 라이브러이 등과 함께 사용할 때 이름이 충돌되는 것을 피하기 위한 한 방편으로 사용된 것입니다.
[code php;gutter:false] <?php class hTemplateCache { /* code */ } class hTemplateCompile { /* code */ } class hTemplateDebug { /* code */ } class hTemplateFile { /* code */ } class hTemplateFilter { /* code */ } class hTemplateFunction { /* code */ } class hTemplateStructure { /* code */ } class hTemplateAssign { /* code */ } class hTemplate extends hTemplateAssign { /* code */ } $tpl = new hTemplate(); ?> [/code]
만약 PHP 5.3.0 버전부터 제공되는 namespace 키워드를 이용한다면 아래와 같이 클래스명에 접두어 hTemplate를 붙이지 않더라도 다른 프로그램과 이름이 충돌하는 것을 피할 수 있을 것입니다.
[code php;gutter:false] <?php namespace hTemplate; class Cache { /* code */ } class Compile { /* code */ } class Debug { /* code */ } class File { /* code */ } class Filter { /* code */ } class Function { /* code */ } class Structure { /* code */ } class Assign { /* code */ } class main extends Assign { /* code */ } $tpl = new hTemplate::main(); ?> [/code]
또 다른 예로 PEAR의 HTTTP 패키지를 살펴보면 아래와 같은 "HTTP", "HTTP_Downlod", "HTTP_Request"와 같은 특정 접두어를 붙인 클래스명을 사용하여 클래스명이 다름 프로그램과 충돌될 가능성을 사전에 피하려고 한 것을 볼 수 있습니다.
HTTP_Download
HTTP_Client
HTTP_Header
HTTP_Request
HTTP_Download_PgLOB
HTTP_Download_Archive
HTTP_Header_Cache
HTTP_Request_Listener
< PEAR HTTP 패키지에서 사용된 클래스명 >
PEAR2 Coding Standards(pear.php.net/manual/en/pear2cs.php)의 Rule을 보면 PEAR2의 모든 클래스와 함수는 아래와 같이 반드시 PEAR2의 네임스페이스를 정의하도록 하고 있습니다. (아래의 세번째 예는 설명을 위해 추가하였음)
[code php;gutter:false] <?php namespace PEAR2; class MyClass { /* code */ } ?> [/code]
[code php;gutter:false] <? namespace PEAR2::HTTP; class Request { /* code */ } ?> [/code]
[code php;gutter:false] <? namespace PEAR2::HTTP::Request; class Listener { /* code */ } ?> [/code]
이와 같이 네임스페이스를 이용하면 클래스명에 더 이상 접두어를 붙일 필요가 없습니다.
Download
Client
Header
Request
PgLOB
Archive
Cache
Listener
< 네임스페이스 지원으로 간략화된 클래스명 >
이와 같이 네임스페이스의 지원으로 간단명료한 클래스명을 사용하여 프로그래밍할 수 있게 되었으며 단지 각 클래스들이 어느 네임스페이스에 속해 있는지만 명확히 지정해주면 됩니다.

Posted by 방글24
phpclass/객체정보2008. 8. 9. 12:28
작성: 2008.08.09
네임스페이스란?
많은 사람들이 네임스페이스(namespace; 이름공간) 개념을 이해하는데 어려움을 겪는 것 같습니다. 2008년 8월 1일 php.net에 정식 릴리즈된 5.3.0 알파1 버전부터 네임스페이스를 지원한다기에 네임스페이스를 이곳에서 다시 한 번 정리하게 되었습니다.
프로그램 소스의 여러 가지 구성요소 중에는 클래스명, 함수명, 변수명, 상수명과 같이 이름(identifier)들이 포함되어 있는데 이러한 이름들이 동일한 이름으로 중복하여 사용하더라도 서로 충돌되지 않도록 해주는 기능이 네임스페이스입니다.
초등학교 교실
예를 들어, 어떤 초등학교 6학년 1반에 홍길동이란 이름을 가진 어린이가 3명 있다고 하면 이 반 담임선생님은 출석을 부를 때마다 곤혹을 치를 것입니다.
키큰 홍길동~
키작은 홍길동~
뚱뚱한 홍길동~
< 6학년 1반에 편성된 3명의 홍길동 어린이 >
그렇다고 아이들보고 이름 바꾸라고 할 수 있습니까? 불편하지만 홍길동 앞에 "키큰", "키작은", "뚱뚱한"과 같은 접두어를 붙일 수 밖에 없겠지요.
사실 이 문제를 근본적으로 해결하려고 했다면 학년초 반편성할 때 3명의 홍길동 어린이를 서로 다른 반으로 편성했을 것입니다.
< 각 반으로 편성되어 관리되고 있는 3명의 홍길동 >
이제는 "키큰", "키작은", "뚱뚱한"이라는 괴상망칙한 수식어를 붙이지 않아도 됩니다. 각 반에서는 모두 수식어 없이 그냥 홍길동이라고 부르면 되고, 같이 있을 때는 1반 홍길동, 2반 홍길동, 3반 홍길동 라고 부르면 되지요.
네임스페이스(namespace; 이름공간)
네임스페이스란 그 이름이 뜻하는 바와 같이 서로 관련된 이름(함수명, 클래스명 ...)을 통합관리하기 위하여 지정하는 공간을 의미합니다. 초등학교 각 반 교실에 해당합니다. 키큰 홍길동은 1반에, 키작은 홍길동은 2반에, 뚱뚱한 홍길동은 3반에 소속시키는 것입니다. 이를 개념적으로 프로그래밍해보면 아래와 같습니다.
[code php;gutter:false] <?php namespace 1반; function 홍길동() { print "나는 키큰 홍길동이다.\n"; } ?> [/code]
[code php;gutter:false] <?php namespace 2반; function 홍길동() { print "나는 키작은 홍길동이다.\n"; } ?> [/code]
[code php;gutter:false] <?php namespace 3반; function 홍길동() { print "나는 뚱뚱한 홍길동이다.\n"; } ?> [/code]
홍길동을 부를 때 1반 홍길동, 2반 홍길동, 3반 홍길동 라고 부르듯이 프로그램 소스에서는 아래와 같이 1반::홍길동(), 2반::홍길동(), 3반::홍길동() 라는 식으로 호출하면 됩니다.
[code php;gutter:false] <?php 1반::홍길동(); 2반::홍길동(); 3반::홍길동(); ?> [/code]
각 반에서 반에 소속된 어린이의 이름을 출석부에 기록하여 관리하는 것처럼 각 네임스페이스에 소속된 이름을 심볼 테이블(symbol table)에 기록하여 관리합니다.

'phpclass > 객체정보' 카테고리의 다른 글

{네임스페이스}3.네임스페이스의 정의  (0) 2008.08.09
{네임스페이스}2.네임스페이스의 필요성  (0) 2008.08.09
What Is an Interface?  (0) 2005.10.25
{참조}5.참조 삭제  (0) 2001.03.02
{참조}4.참조 반환  (0) 2001.03.02
Posted by 방글24