phpsource/클래스&객체2001. 4. 12. 10:45
인풀링 클래스는 인스턴스 풀링(Instance Pooling)을 흉내내기 위해 작성된 클래스입니다.
인스턴스 풀링이란 자주 사용하는 객체를 메모리에 상주시키고, 보다 빠르게 객체를 사용할 수 있도록 하는 것입니다. 동시에 많은 사용자가 접속했을 때 이미 메모리에 올라온 인스턴스가 있으면 그것을 사용하고, 올라온 내용이 없을 때는 인스턴스를 하나 더 만듭니다.
이러한 인스턴스 풀링은 PHP에서 내장하여 지원하여야만 효과적으로 사용할 수 있을 것입니다. 그러나 지원되지 않으니 좀 미숙하더라도 편리하게 사용될 것 같아 인풀링 클래스를 작성하여 공개합니다.
이것은 Q&A 게시판에 채명신 님이 질의하신 내용에 대한 결과로 얻어진 것입니다.
아래는 채명신 님의 질문 내용의 요약입니다.
[채명신 님의 질문 내용]
생성한 클래스를 다른 사람이 참조할수 있는 방법은요?
자바에서의 풀링 기법과 비슷하다고나 할까??
그러니까 한번 생성된 클래스는 (특히 복잡한 계산에의해 생성된 클래스를) 클라이언트의 요청시마다 독립적인 각각의 클래스를 새로 만들어서 자신이 만든 클래스만을 참조 하는것이 아니라, 기존에 만들어진 클래스가 있다면 그것을 참조 하는 것이죠. 그니까 제일 처음에 로그인함 사람이 만들면 컴이 꺼진기전에 다른 사람은 만든 글래스를 그냥 공유 해서 쓰는 것이죠.
[답장 내용]
개체 또는 인스턴스 풀링(instance pooling)을 원하시는 것 같네요. PHP에서는 영구접속 방법을 통한 데이터베이스 풀링이 지원되기는 하지만 인스턴스 풀링까지는 지원되지 않는 것 같습니다. 하지만 마음만 먹는다면 흉내는 얼마든지 낼 수 있겠지요. 좀 복잡해 지겠지만 이것도 함수 또는 클래스로 미리 작성해 놓고 사용하면 쓸만하겠네요. 인스턴스 풀링을 흉내내기 위해 필요한 것을 살펴보지요.
1. 모든 방문자가 공유하는 영역 만들기
이것은 제가 공개한 애플리케이셔너를 참조하시든지 아니면 세션파일과 같이 /tmp 에 모든 방문자가 공유할 파일을 생성시키면 되겠지요. 인스턴스 풀링처럼 필요한 정보를 메모리에 상주시키려면 공유메모리를 이용하면 되겠지요. 이러한 공유영역에는 복수의 방문자가 공유할 생성된 클래스 정의와  객체가 저장되겠지요.
2. 메소드 및 프로퍼티의 직렬화/객체화하기
객체 멤버를 다른 페이지로 넘기기 위해서는 PHP4에서 지원하는 serialize() 함수와
unserialize() 함수를 이용하셔야 합니다. 이에 대한 자세한 정보는 제 홈페이지 "핍클래스홈 >> 객체에 관련된 정보 >> Serialize/Unserialize 또는 메소드 다루기(PHP4)"를 참조하세요. 추가적으로 말씀드린다면 serialize/unserialize 함수에서는 객체멤버를 다루기는 하지만 클래스를 다루어 주지 않거든요. 사실 Serialize/Unserialize 정보를 공개하면서도 클래스 정의 부분을 포함시킬까 말까하고 고민을 하였었는데 복잡해 질 것 같아 생략했었지요.
아무튼 위 두가지에 대한 지식만 가지고 계시다면 님도 원하시는 인스턴스 풀링 기능을 흉내낼 수 있는 함수를 작성할 수 있으리라 봅니다. 위에서도 이야기했지만 다른 것보다도 클래스 정의 부분을 공유하는 것만 주의한다면 별 어려움은 없을 것입니다.
함수로 만들어 놓으면 상당히 유용한 기능이 될 것 같네요. 앞으로 시간이 허락되면 작성하여 공개하고 싶군요.
[채명신 님의 재질의 내용]
그니까  말씀 하신 방법중에 "인스턴스 풀링처럼 필요한 정보를 메모리에 상주시키려면 공유메모리를 " 이용하면 되겠지요. 이러한 공유영역에는 복수의 방문자가 공유할 생성된 클래스 정의와  객체가 저장되겠지요......................ㅠ.ㅠ"
이 메모리는 어커 쎠야 하는지요  ㅠ.ㅠ ??????
관련 소스나 참고 알고리즘이 있으시면 도움을 바랍니다. 13 일 까지 해결 해야 하는데........ 내가 이해나 할수 있을까.  흑흑
 초보자인 저는 더욱 난해 하네요.. 다시한번 답변은 정말 감사 합니다  그러나. 공유 메모리...ㅠㅠ 그놈의 메모리는 .... 지금은 시간이 없는 관계로 없는 실력으로 자바로 써볼려고 합니다 ..
언제가  만들어지면  이용 해야겠네요 ^^ 또 이런 비슷한 일이 생기면 ........... 도움을 많이 받아 갑니다.. 헤헤 ^ ^
그럼 시간이 되시면 부탁 드립니다 . 감사 감사
[재답장 내용]
우선 급한대로 인스턴스 풀링을 구현하는 클래스를 조잡하게나마 작성하여 Tip&Tech&Download 게시판에 올렸습니다. 자세한 사용법까지 설명할 수는 없고 테스트용 샘플도 포함시켰으니 살펴보세요.
(수정:2010.1.12) 홈페이지 이동으로 여기에서 다운로드 받으세요.
모든 방문자가 공유할 클래스 정의는 이벤트 파일에 변수로서 저장하게 됩니다. 물론 일반 텍스트 파일로도 작성할 수도 있으며 이렇게 하여야 될 것 같으나 시간이 더 걸릴 것 같아 급한대로 변수에 저장시켰습니다.
인풀링 클래스(인스턴스 풀링을 흉내내기 위해 작성된 클래스) 사용상의 주의점
1. 위에서도 언급했듯이 급하게 만들다보니 버그가 상존하지 않을까 걱정됩니다.
2. 공유메모리와 세마포어를 이용하여 작성되었습니다. 그러나 공유메모리용 함수가 PHP 4.0.4부터 성능이 대폭 개선된 함수를 새로이 제공되고 있으나 여기에서는 기존의 공유메모리 함수인 shm_...()함수를 사용하였습니다. 그러니 PHP 4.0.4를 사용하시는 분은 개선된 공유메모리 함수인 shmop_...() 함수를 사용하세요.
3. 모든 방문자가 공유할 클래스 정의는 이벤트 파일에 변수로서 저장하도록 하였습니다. 이부분을 좀 더 개선한다면 일반 텍스트 파일로 작성하는 것이 바람직할 것입니다. 아래는 파일에 첨부된 이벤트 파일 내용입니다. 이 이벤트 파일에 있는 pooling_onStart() 함수는 최초의 방문자가 방문할 때만 실행하게 됩니다. 이 함수에서 돌려주는 $class에 클래스 정의가 담겨지며 되돌려진 $class의 내용은 인풀링 클래스 내에서 객체로 생성한 후 공유메모리에 클래스 정의와 객체가 함께 저장하여 다음 방문자들이 공유할 수 있도록 합니다.
[code php;gutter:false] function pooling_onStart() {
$class = "
class test {
var \$a = 1000;
var \$b = "\\\$b값";

function output() {
return "나 함수";
}
}
";
return $class;
} [/code]
클래스 정의를 $class와 같은 변수에 담을 것이 아니라 아래와 같이 텍스트 파일에 저장한 후 인풀링 클래스에서 읽어들이는 것이 좋을 것입니다.
[code php;gutter:false] class test {
var $a = 1000;
var $b = "\$b값";

function output() {
return "나 함수";
}
} [/code]
이렇게 하니까 가독성이 훨씬 좋지 않습니까? 이것을 구현하는 것을 여러분이 해보시지 않겠습니까? 제가 해도 되겠지만...
4. 아래는 인풀링 클래스를 테스트하는 프로그램 test.php입니다. 이 파일도 첨부되어 있습니다.
[code php;gutter:false] <?php
require("./class.poolshm.php");

$ip =& new inPooling;
if ("delete" == $exec)
$ip->delete();
$obj =& $ip->read();

echo $obj->a."\n";
echo $obj->b."\n";
echo $obj->output()."\n";

$obj->b = $exec;
$ip->write($obj);
$ip->close();
?> [/code]
아래와 같은 방법으로 서로 다른 컴퓨터에서 아니면 다른 브라우저로 실험해 보세요.
http://....../inpooling/test.php
http://....../inpooling/test.php?exec=delete
http://....../inpooling/test.php?exec=연습
화면에는 아래와 같이 나타날 것입니다. 여기서 두번째 줄의 내용을 URL의 exec파라미터의 값에 따라 계속 변할 것이고 exec값이 "delete"이면 현재의 공유메모리의 내용이 지워집니다.
1000
$b값
나 함수
5. 인풀링 클래스는 PHP 4 버전에서만 사용할 수 있습니다. PHP 3.x.x에서는 지원하지 않는 레퍼런스(참조)를 사용하였습니다. 참조에 대한 자세한 설명은 제 홈페이지 "class & object>> 참조(레퍼런스)"를 보세요.

Posted by 방글24
Ver 0.1.0 (2002.2.12)
  • classopen() 함수를 newobject()함수로 함수명 변경 및 인터페이스 변경
  • classinfo() 함수를 classchain()함수로 함수명 변경 및 인터페이스 변경
  • 함수 오버로딩(function overloading) 기능 삭제
  • 복수의 객체 생성 허용
  • 정적 데이터멤버(static data member) 지원 방법 변경
  • 사용자 정의 생성자 및 소멸자 명명방법 변경
  • PHP 4.0.4부터 지원하는 레퍼런스 기능을 사용한다. 따라서 4.0.3 이하 버전에서는 동작되지 않는다.
2000.7.10
  • 소멸자에서의 데이터멤버 인식 오류를 수정하기 위한 객체생성함수 수정 -> newobject() 함수를 classopen()함수로 함수명 변경 및 내용 수정
2000.7.6
  • "정적 데이터멤버" 인식 오류 수정
2000.7.5
  • 사용함수를 3개로 축소
    classdefine() : 클래스 정의 해석 함수
    newobject() : 객체 생성 함수
    classinfo() : 클래스 상속 관계 표시 함수
  • 객체 생성 함수의 전달 인자의 수량 및 데이터형 수정
2000.6.9
  • PHP4까지 사용범위 확대 -> PHP3와 PHP4에서 모두 사용 가능
  • 다중상속을 단일상속으로 변경해주는 알고리즘 개선으로 상속관계가 단순화됨
  • 정적 데이터멤버(static data member) 지원
2000.5.30
  • 동일 클래스 내에서 복수의 함수 오버로딩(function overloading) 정의 가능하도록 함수 오버로딩 기능 확장
  • 생성자에 인수(argument)를 10개까지 전달하도록 수정
  • "사용자 정의 생성자"를 정의하기 위한 예약어 "constructor"를 지정하지 않고도 "사용자 정의 생성자"를 정의할 수 있도록 수정
  • 소멸자(destructor) 지원
2000.5.18 민주화운동기념일
  • 함수 오버로딩(function overloading) 기능 추가
  • 전역변수 $gClassobject 추가
2000.5.5 어린이날
  • 최상위 클래스로부터 모든 파생클래스의 생성자 실행 지원
  • 다중상속(multiple inheritance) 지원
  • 동일한 조상클래스(ancestor class)를 가진 클래스의 다중상속 지원

Posted by 방글24
정적 데이터멤버란?
생성된 모든 객체들이 공유하는 공통적인 정보가 필요할 때에 사용되는 것이 정적멤버(static data member)입니다. "정적 데이터멤버"는 다른 일반 데이터 멤버와 달리 각각의 객체에 기억장소가 할당되는 것이 아니라, 단 한 개의 기억장소만이 할당되고 모든 객체에 의하여 공유됩니다. 하지만 데이터 멤버의 정보는 각각의 객체가 모두 가지고 있는 것처럼 간주됩니다. 이와 같이 모든 객체에서 공통되는 데이터 멤버를 정적 데이터멤버로 선언하므로 써, 모든 객체에서 중복되는 기억장소를 절약할 수 있습니다. 예를 들어 물건을 파는 상점에서 각 물품에 대한 객체는 별도로 생성되더라도 물품을 판 수입금액은 결국 각 객체가 공유해야하는 데이터이지요. 이와 같이 모든 객체가 공유해야 하는 데이터를 정적멤버로 정의하여 사용하면 편리하지요.
PHP에서의 정적 데이터멤버
PHP에서는 정적 데이터멤버를 지원하지 않습니다. 만약 PHP에서 정적 데이터멤버를 흉내내려면 가장 쉬운 방법이 전역변수를 이용하는 방법입니다. PHP에서의 정적 데이터멤버를 흉내내는 방법에 대한 것은 메뉴 "핍클래스홈>>객체지향언어로서의 PHP>>정적 데이터멤버"를 참조바랍니다.
정적 데이터멤버 지원
후키라이브러리에서는 이러한 정적 데이터멤버를 쉽게 사용할 수 있도록 하였습니다. 이전 버전에서는 classdefine 함수 내에서 정적 데이터멤버를 정의하도록 하였습니다. 그러나 classdefine 함수 내에서 정적 데이터멤버를 정의해 주려면 문자열 작성 규칙이 까다로워 사용하기가 상당히 불편하였습니다. 그래서 굳이 classdefine 함수 내에서 정의할 필요가 없이 어느 곳에서나 특별한 정의없이 사용할 수 있도록 0.1.0 버전에서는 수정하였습니다. 대략 사용방법은 아래와 같습니다.
[code php;gutter:false] <?php

classdefine("
class BankInterclass extends clsString, clsArray, clsDate {}
");

//
// 데이터멤버 $this->SAVINGS 에는 각 사람(객체)마다의 저축 내용을 기록
// 정적 데이터멤버 $this->STATIC->SAVINGS 에는 모든 사람의 저축을 합하여 기록
//
class Bank extends BankInterclass {
var $SAVINGS_FILE = "/tmp/savings";
var $SAVINGS = 0; // 저금통장

//
// 생성자
//
function Bank($argv) { }

//
// 소멸자
//
function _Bank() { }

function add($savings) {
$this->SAVINGS += $savings;
$this->STATIC->SAVINGS += $savings;
}

function subtract($savings) {
$this->SAVINGS -= $savings;
$this->STATIC->SAVINGS -= $savings;
}

function reset() {
$this->STATIC->SAVINGS = 0;
}

function print_family() {
print "우리가족 총 저금액=" . $this->STATIC->SAVINGS . "원\n";
}

function print_person($name="나") {
if ($this->SAVINGS > 0) {
$t = "저금액";
} else {
$this->SAVINGS = abs($this->SAVINGS);
$t = "지출액";
}
print "${name}의 $t=" . $this->SAVINGS . "원\n";
}
}

?> [/code]
이 예에서 보는 바와 같이 정적 데이터멤버의 경우는 $STATIC 데이터멤버를 통해 접근하도록 되어 있습니다.
[code php;gutter:false] $this->STATIC->SAVINGS -= $savings; [/code]
여기에서 데이터멤버 $SAVINGS는 모든 객체에서 공유하게 되는 정적 데이터멤버라고 할 수 있습니다.

Posted by 방글24
생성자 및 소멸자 체인
일반적인 객체지향언어에서 보면 클래스 객체를 생성할 때마다 생성자가 실행되는데 객체를 생성할 때에 먼저 부모클래스의 생성자를 호출한 후 자식클래스의 생성자를 호출합니다.
그러나 PHP3 또는 PHP4 스크립트에서는 마지막으로 파생된 클래스의 생성자만을 호출하고 그 이상의 부모클래스의 생성자는 실행하지 않고 종료합니다. PHP에서의 생성자 동작 원리는 좀 더 복잡합니다. 자세한 것은 메뉴 "핍클래스홈>>클래스 사용법>>생성자"를 참조하기 바랍니다.
따라서 클래스를 정의할 때는 연속된 생성자 실행(생성자 체인)을 위해 반드시 생성자를 정의하고 그 생성자 내에서 부모클래스에 대한 생성자를 호출할 필요가 있습니다.
반면 클래스 객체가 파괴될 때마다 클래스 소멸자가 실행되는데 프로그램은 먼저 자식클래스의 소멸자를 호출한 후 부모클래스의 소멸자를 호출합니다.
"후키라이브러리"를 이용하여 클래스를 정의하면 생성자 및 소멸자 체인을 자동으로 구현할 수 있습니다.
[code php;gutter:false] /*
파일명 class.c.php
조상클래스 c 정의
*/

classdefine("
class cInterclass {}
");

class c extends cInterclass {
function c() {
.... 생성자에서 처리할 내용을 이곳에 작성합니다.
}

function _c() {
.... 소멸자에서 처리할 내용을 이곳에 작성합니다.
}

.... 이곳에 조상클래스 c의 멤버함수 및 데이터멤버를 정의합니다.
}

/*
파일명 class.b.php
부모클래스 b 정의
*/

blassdefine("
class bInterclass extends c {}
");

class b extends bInterclass {
function b() {
.... 생성자에서 처리할 내용을 이곳에 작성합니다.
}

function _b() {
.... 소멸자에서 처리할 내용을 이곳에 작성합니다.
}

.... 이곳에 부모클래스 b의 멤버함수 및 데이터멤버를 정의합니다.
}

/*
파일명 class.a.php
자식클래스 a 정의
*/

classdefine("
class aInterclass extends b {}
");

class a extends aInterclass {
function a() {
.... 생성자에서 처리할 내용을 이곳에 작성합니다.
}

function _a() {
.... 소멸자에서 처리할 내용을 이곳에 작성합니다.
}

.... 이곳에 자식클래스 a의 멤버함수 및 데이터멤버를 정의합니다.
} [/code]
클래스 a를 이용하여 객체를 생성한다면 객체를 생성할 때 생성자 체인에 의해 c, b, a 생성자가 순서대로 실행되며, 현 문서가 종료되는 시점에서 소멸자 체인에 의해 _a, _b, _c 소멸자가 순서대로 실행됩니다.
소멸자는 문서가 종료되는 시점에서 수행되기 때문에 현 문서가 출력되는 페이지에서는 그 실행여부를 확인할 수 없습니다. 만약 소멸자의 실행여부를 확인하려면 소멸자 실행 내용을 파일 등에 기록한 후 다음 페이지에서 이 파일 내용을 확인하면 될 것입니다.
[code php;gutter:false] class a extends aInterclass {
function a() {
.... 생성자에서 처리할 내용을 이곳에 작성합니다.
}

function _a() {
if ($fp=@fopen("/tmp/destr.txt", "a+")) {
flock($fp, LOCK_EX);
fwrite($fp, "_a() 실행 \n");
flock($fp, LOCK_UN);
fclose($fp);
}
}
} [/code]

Posted by 방글24
다중 상속이란?
다중 상속(multiple inheritance)은 자식클래스가 하나 이상의 부모클래스로부터 그 특성을 상속받는 것을 말합니다. 다중 상속된 자식클래스는 모든 부모클래스의 데이터멤버 및 멤버함수의 특성을 다 가지게 되므로 부모클래스의 데이터멤버 및 멤버함수를 사용할 수 있습니다.
다중상속의 필요성
객체지향 프로그래밍을 하다보면 많은 경우에 접하게 되는 것이 다중 상속 개념입니다. 다중 상속이야말로 특성 상속의 가장 기본적인 것이라고 할 수 있습니다.
< 다중 상속의 예 >
그림의 예에서 보듯이 서로 독립적인 4개의 클래스(더하기, 빼기, 곱하기, 나누기 클래스)로부터 데이터멤버 및 멤버함수를 상속받은 계산기 클래스가 만들어지게 됩니다.
PHP에서의 다중 상속
PHP에서는 단일상속에 관하여는 별문제없이 그 부모클래스의 특성을 상속받을 수 있습니다. 그러나 복수의 부모클래스의 특성을 상속받을 수는 없습니다. 이러한 다중상속의 문제는 웹사이트 구조가 복잡해 질 수록 절실해지게 되며, 자원(클래스)의 재사용이란 측면에서 볼 때도 꼭 필요한 기능이라고 할 수 있습니다. 이러한 다중상속을 후키라이브러리를 이용하면 손쉽게 구현할 수 있습니다.
다중 상속 정의하기
[code php;gutter:false] /*
파일명 class.더하기.php
부모클래스 더하기 정의
*/

classdefine("
class 더하기Interclass {}
");

class 더하기 extends 더하기Interclass {
.... 이곳에 부모클래스 더하기의 멤버함수 및 데이터멤버를 정의합니다.
}

/*
파일명 class.빼기.php
부모클래스 빼기 정의
*/

classdefine("
class 빼기Interclass {}
");

class 빼기 extends 빼기Interclass {
.... 이곳에 부모클래스 빼기의 멤버함수 및 데이터멤버를 정의합니다.
}

/*
파일명 class.곱하기.php
부모클래스 곱하기 정의
*/

classdefine("
class 곱하기Interclass {}
");

class 곱하기 extends 곱하기Interclass {
.... 이곳에 부모클래스 곱하기의 멤버함수 및 데이터멤버를 정의합니다.
}

/*
파일명 class.나누기.php
부모클래스 나누기 정의
*/

classdefine("
class 나누기Interclass {}
");

class 나누기 extends 나누기Interclass {
.... 이곳에 부모클래스 나누기의 멤버함수 및 데이터멤버를 정의합니다.
}

/*
파일명 class.계산기.php
자식클래스 계산기 정의
*/

classdefine("
class 계산기Interclass extends 더하기, 빼기, 곱하기, 나누기 { }
");

class 계산기 extends 계산기Interclass {
.... 이곳에 자식클래스 계산기의 멤버함수 및 데이터멤버를 정의합니다.
} [/code]
위와 같은 예를 보면 현재클래스 계산기는 부모클래스 더하기, 빼기, 곱하기 및 나누기로부터 다중 상속받도록 되어 있습니다.
classdefine 함수는 클래스 정의 문자열을 해석하면서 클래스 다중 상속을 지원할 수 있도록 상속에 필요한 부모클래스 정의 파일을 인클루드 시킵니다. PHP 스크립트는 클래스 다중 상속을 지원하지 않기 때문에 클래스 정의 문자열을 해석하면서 단일 상속으로 변환시켜 줍니다. 즉, 다중 상속을 단일 상속형태로 변환시켜 주는 역할을 자동적으로 수행합니다.
동일한 조상클래스(ancestor class)를 가진 다중 상속
동일한 부모클래스로부터 서로 다른 길을 통해 상속된 두 개 이상의 파생클래스를 다중 상속할 수 있습니다. 동일한 클래스를 두번 이상 정의하게 되면 PHP는 에러를 발생시킵니다. 이러한 문제를 해결하기 위해 "후키라이브러리"에서는 동일한 부모클래스를 단 한번만 포함하도록 동작합니다. 이는 C++에서 가상클래스(virtual class)를 이용하는 것과 비슷한 기능을 한다고 볼 수 있습니다. 즉, 가상클래스를 이용하는 것은 파생클래스가 동일한 부모클래스를 여러 번 상속했다고 하더라도 하나의 클래스만을 파생클래스에 포함시키도록 하는 것입니다.
< 동일한 조상클래스를 가진 다중 상속의 예 >
[code php;gutter:false] /*
파일명 class.숫자.php
조상클래스 숫자 정의
*/

classdefine("
class 숫자Interclass {}
");

class 숫자 extends 숫자Interclass {
.... 이곳에 조상클래스 숫자의 멤버함수 및 데이터멤버를 정의합니다.
}

/*
파일명 class.더하기.php
부모클래스 더하기 정의
*/

classdefine("
class 더하기Interclass extends 숫자 {}
");

class 더하기 extends 더하기Interclass {
.... 이곳에 부모클래스 더하기의 멤버함수 및 데이터멤버를 정의합니다.
}

/*
파일명 class.빼기.php
부모클래스 빼기 정의
*/

classdefine("
class 빼기Interclass extends 숫자 {}
");

class 빼기 extends 빼기Interclass {
.... 이곳에 부모클래스 빼기의 멤버함수 및 데이터멤버를 정의합니다.
}

/*
파일명 class.곱하기.php
부모클래스 곱하기 정의
*/

classdefine("
class 곱하기Interclass extends 숫자 {}
");

class 곱하기 extends 곱하기Interclass {
.... 이곳에 부모클래스 곱하기의 멤버함수 및 데이터멤버를 정의합니다.
}

/*
파일명 class.나누기.php
부모클래스 나누기 정의
*/

classdefine("
class 나누기Interclass extends 숫자 {}
");

class 나누기 extends 나누기Interclass {
.... 이곳에 부모클래스 나누기의 멤버함수 및 데이터멤버를 정의합니다.
}

/*
파일명 class.계산기.php
자식클래스 계산기 정의
*/

classdefine("
class 계산기Interclass extends 더하기, 빼기, 곱하기, 나누기 { }
");

class 계산기 extends 계산기Interclass {
.... 이곳에 자식클래스 계산기의 멤버함수 및 데이터멤버를 정의합니다.
} [/code]
다중 상속으로 생기는 문제점
다중 상속이 가진 문제점은 클래스 상속 구조가 매우 복잡해지고, 멤버 특성의 상속 관계가 모호해 진다는 것입니다.
예를 들면, 만일 동일한 이름의 데이터멤버 x가 더하기, 빼기 클래스에서 각각 정의되어 있을 때 더하기, 빼기 클래스를 다중으로 상속받게 되는 계산기 클래스에서 데이터멤버 x에 접근할 때 더하기 클래스에 있는 데이터멤버 x에 접근해야 할지 아니면 빼기 클래스에 있는 데이터멤버 x에 접근해야 할지 혼란이 발생하게 됩니다. 따라서 각 클래스에서 데이터멤버를 정의할 때는 하위클래스에서 동일한 이름의 데이터멤버를 참조할 경우를 대비하지 않으면 안됩니다. 이러한 문제는 멤버함수를 정의할 때도 동일하게 나타나는 문제입니다.
아래 예와 같이 다중 상속되었을 경우를 보면 후키라이브러리에서는 왼쪽에 있는 자식클래스에서 우선적으로 멤버를 찾게 됩니다. 이 예에서는 더하기에 있는 데이터멤버 또는 멤버함수를 먼저 참조하도록 되어 있습니다. 더하기에서 찾지못하였으면 빼기에서, 빼기에서 찾지 못하였으면 곱하기에서, 곱하기에서 찾지 못하였으면 나누기에서 찾게됩니다. 이러한 규칙은 파이썬과 유사하다고 할 수 있습니다.
[code php;gutter:false] classdefine("
class 계산기Interclass extends 더하기, 빼기, 곱하기, 나누기 { }
");

class 계산기 extends 계산기Interclass {
.... 이곳에 자식클래스 계산기의 멤버함수 및 데이터멤버를 정의합니다.
} [/code]
그러나 이러한 규칙에 의존하여 클래스를 정의하지 말기 바랍니다. 이는 매우 관리하기 힘들고 약간의 실수에도 큰 문제를 발생시킬 수 있기 때문에 가능하면 각 클래스 별로 다른 클래스와 구분할 수 있는 멤버 이름을 사용할 것을 권합니다. 꼭 다중 상속을 이용해서만이 아니더라도 PHP에서는 멤버의 접근 권한(access right)을 임의로 지정할 수 없으며 무조건 public으로 설정되도록 되어 있기때문에 이 문제는 항상 상존한다고 보아야 합니다. C++의 경우를 보면 멤버의 접근 권한이 public 외에도 private, protected를 선택할 수 있으며 private를 지정할 경우에 하위클래스에서 동일한 이름의 멤버를 접근하는데 혼란이 발생하지는 않을 것입니다.

Posted by 방글24
1. classdefine : 클래스 정의 함수
2. newobject : 객체 생성 함수
3. classchain : 클래스 상속관계 반환 함수
클래스 정의 함수 classdefine
[code c;gutter:false] string classdefine(string def_class); [/code]
기능
클래스 정의 문자열을 입력받아 해석하여 후키라이브러리에서 지원하는 기능을 사용할 수 있도록 합니다.
클래스 정의
보통 클래스를 정의하려면 아래와 같이 클래스 내에 멤버함수 및 데이터멤버를 정의하게 될 것입니다.
[code php;gutter:false] /*
클래스 a 정의
*/

class a {
.... 이곳에 멤버함수 및 데이터멤버를 정의합니다.
} [/code]
후키라이브러리를 이용하여 클래스 a를 정의하려면 아래와 같이 classdefine 함수로 현재클래스에 대한 중간클래스를 먼저 정의하여야 하며 현재클래스는 extends 키워드를 이용하여 중간클래스와의 관계를 정의해 주어야 합니다. 중간클래스명은 현재클래스명에 "Interclass"를 붙여줍니다. 그리고 나서 현재클래스 내에 멤버함수 및 데이터멤버를 정의하여 주면 됩니다.
[code php;gutter:false] /*
클래스 a 정의
*/

classdefine("
class aInterclass {}
");

class a extends aInterclass {
.... 이곳에 멤버함수 및 데이터멤버를 정의합니다.
} [/code]
단일 상속의 예
보통 PHP에서는 클래스 a가 부모클래스 z로부터 그 특성을 상속받으려는 자식클래스라면 아래와 같이 extends 키워드를 이용하여 그 관계를 정의하여 주게 되지요.
[code php;gutter:false] /*
부모클래스 z 정의
*/

class z {
.... 이곳에 부모클래스의 멤버함수 및 데이터멤버를 정의합니다.
}

/*
자식클래스 a 정의
*/

class a extends z {
.... 이곳에 자식클래스의 멤버함수 및 데이터멤버를 정의합니다.
} [/code]
후키라이브러리를 이용하여 단일 상속받으려면 아래와 같이 extends 키워드를 이용하여 그 관계를 정의하여 주게 되지요. 이 때 classdefine() 함수로 중간클래스를 먼저 정의하여야 하며 여기에서 현재클래스와 부모클래스 사이를 extends 키워드를 이용하여 연결해 줍니다.
[code php;gutter:false] /*
파일명 class.z.php
부모클래스 z 정의
*/

classdefine("
class zInterclass {}
");

class z extends zInterclass {
.... 이곳에 부모클래스의 멤버함수 및 데이터멤버를 정의합니다.
}

/*
파일명 class.a.php
자식클래스 a 정의
*/

classdefine("
class aInterclass extends z {}
");

class a extends aInterclass {
.... 이곳에 자식클래스의 멤버함수 및 데이터멤버를 정의합니다.
} [/code]
위에서 한가지 주의할 점은 부모클래스 z와 자식클래스 a는 반드시 별도의 파일로 관리하여야 합니다.
다중 상속의 예
다중 상속에 관한 자세한 내용은 "다중 상속" 장을 참조바랍니다.
중간클래스의 접미어를 변경하는 방법
접미어 "Interclass"를 디폴트 값이며 다른 접미어를 사용하려면 classdefine 함수의 두번째 인자로 지정하여 주면 됩니다. 아래는 "Interclass" 대신에 "Linkclass"를 접미어로 지정하는 예를 보여줍니다.
[code php;gutter:false] classdefine("
class aLinkclass extends b { }
", "Linkclass");

class a extends aLinkclass {

} [/code]
객체 생성 함수 newobject
[code php;gutter:false] include("./lib.hwooky.php"); // 후키라이브러리(0.1.0)

$obj = & newobject(CLASS_NAMES, ARGV); [/code]
기능
멤버 특성을 상속하려는 1개 이상의 부모클래스명 및 필요한 입력인자를 지정하게 되면 새로운 클래스 객체를 생성하여 되돌려 줍니다. 클래스 객체를 생성하기 전에 지정된 모든 부모클래스를 정의한 파일들을 순서대로 인클루드 시켜 줍니다.
부모클래스명 CLASS_NAMES
[code php;gutter:false] $obj = & newobject("clsDate", ARGV); [/code]
CLASS_NAMES은 상속받으려는 부모클래스명을 지정합니다. 위의 예에서는 클래스 "claDate"로 부터 객체를 생성합니다. newobject 함수에서 직접 다중상속하려는 경우에는 아래와 같이 복수 개의 부모클래스를 콤마(,)로 분리하여 지정합니다. 이 때 지정되는 순서는 자식클래스로부터 부모클래스 순으로 합니다. 따라서 아래의 예에서는 클래스 Bank가 마지막 파생클래스가 됩니다.
[code php;gutter:false] $obj = & newobject("Bank, clsDate", ARGV); [/code]
클래스 파일 관리 classfile.info
클래스 파일 관리는 classfile.info 파일 내에서 일괄적으로 다루어주기 때문에 사용자가 작성하는 스크립트 내에서는 파일 위치 또는 파일명을 지정하지 않아도 됩니다. 대신에 classfile.info 파일의 위치는 newobject()의 두번째 인자인 배열의 한 요소(첨자명 "path-to-classfile")로 지정됩니다.
[code php;gutter:false] $argv = array(
"path-to-classfile" => "./class"
);

$father = & newobject("Bank", $argv); [/code]
위와 같이 classfile.info의 위치를 "./class"를 지정하게 되면 현 문서의 하위디렉토리인 "./class"에서 classfile.info 파일을 찾게 됩니다. 이곳에 이 파일이 존재하지 않게되면 에러가 발생하게 되지요. classfile.info 파일에는 연관배열로 각 클래스명에 해당되는 클래스 정의 파일의 위치와 파일명이 할당되어 있습니다. 이 때 배열명은 반드시 $hkClassSpec로 지정하여야 합니다.
[code php;gutter:false] <?php

/*
classfile.info
*/

$hkClassSpec["clsDbsql"] = "base/class.mysql.php";
$hkClassSpec["clsSession"] = "session/class.session.php";
.
.
.

?> [/code]
classfile.info에 지정된 디렉토리 "base" 및 "session"은 classfile.info 파일이 있는 곳을 기준으로 지정합니다. 이와 같은 규칙만 지켜준다면 상호 독립적인 클래스를 별도의 디렉토리 별로 저장하여 관리할 수 있으며, 필요에 따라 필요한 클래스를 모두 쉽게 상속받아 사용할 수 있을 것입니다. 지정되는 디렉토리는 classfile.info 파일의 위치를 기준으로 지정하게 되며 현재 디렉토리를 의미하는 "."은 붙이지 않습니다.
입력값 ARGV
newobject 함수의 두번째 입력인자인 ARGV는 위에서 설명한 "path-to-classfile" 외에도 클래스 내에서 필요한 모든 입력인자를 지정할 수 있습니다. 이와같이 지정된 ARGV는 최상위 클래스로부터 최하위 클래스까지 모든 생성자에 동일하게 전달됩니다. ARGV의 데이터형은 연관배열(associative array)이며 객체 생성할 때에 필요한 인자를 배열에 담아 부모클래스 생성자로 전달합니다. 따라서 필요한 만큼 제한 없이 인자를 지정할 수 있습니다.
[code php;gutter:false] $argv = array(
arg1 => "입력값1",
arg2 => "입력값2",
.
.
.
);

$obj = & newobject("Bank", $argv); [/code]
리턴값
생성된 클래스 객체를 되돌려 줍니다. 반환된 객체는 아래 예에서와 같이 반드시 참조로 받아야 합니다. 참조로 받지 않으면 대부분의 경우에는 정상적으로 동작하지만 소멸자에서 데이터멤버를 다룰 때와 같은 경우에는 정상적으로 동작하지 않습니다.
[code php;gutter:false] $argv = array(
"path-to-classfile" => "./class"
);

$obj = & newobject("Bank, clsDate", $argv);

$obj->abc(); // abc()가 멤버함수로 정의되어 있다면... [/code]
복수의 객체를 생성할 때
아래는 동일한 상속 관계를 유지하는 클래스를 이용하여 복수 개의 객체를 생성하는 방법입니다.
[code php;gutter:false] $argv = array(
"path-to-classfile" => "./class"
);

$father = & newobject("Bank", $argv);
$mother = & newobject("Bank", $argv);
$son = & newobject("Bank", $argv); [/code]
위의 예와 다른 상속 관계를 가지고 있는 클래스를 이용하여 위와 동시에 객체를 생성할 수도 있습니다.
[code php;gutter:false] $argv = array(
"path-to-classfile" => "./class"
);

$father = & newobject("Bank", $argv);
$mother = & newobject("Bank", $argv);
$son = & newobject("Bank", $argv);

$argv["path-to-classfile"] = "./class/logic";

$o1 = & newobject("Group", $argv);
$o2 = & newobject("Group", $argv);
$o3 = & newobject("Group", $argv); [/code]
클래스 Bank와 클래스 Group이 서로 다른 classfile.info에 기록/유지되고 있다면 위에서와 같이 "path-to-classfile"를 객체 생성 직전에 올바르게 지정하여 주어야 합니다. 위의 예에서 보면 클래스 Bank는 현 문서를 기준으로 "./class/classfile.info"에 기록되어 있으며 클래스 Group는 "./class/logic/classfile.info"에 기록되고 있음을 알 수 있습니다.
클래스 상속관계 반환 함수 classchain
[code php;gutter:false] classchine(CLASS_NAMES); [/code]
기능
이전 버전의 classinfo 함수와는 달리 클래스의 상속관계를 브라우저에 표시하지 않고 단지 상속관계를 배열에 담아 되돌려 줍니다.
설명
배열에는 최상위 클래스명부터 최하위 파생클래스명까지 순서대로 기록되어 있습니다. classchine 함수를 사용하기 위해서는 먼저 newobject 함수를 실행하여야 하며, newobject 함수가 실행된 후에는 어느 곳에서나 실행할 수 있습니다. classchain 함수에 지정하게 되는 입력인자는 newobject 함수에서 지정하였던 첫번째 입력인자를 의미합니다.
사용예
[code php;gutter:false] function print_chain($names) {
$chain = classchain($names);
$str = $indent = "";

foreach ($chain as $classname) {
$str .= "$indent$classname\n";
$indent .= ".";
}

print $str;
}

include("./lib.hwooky.php"); // 후키라이브러리(0.1.0)

$argv = array(
"path-to-classfile" => "./class"
);

$father = & newobject("Bank", $argv);
$mother = & newobject("Bank", $argv);
$son = & newobject("Bank", $argv);

$argv["path-to-classfile"] = "./class/logic";

$o1 = & newobject("Group", $argv);
$o2 = & newobject("Group", $argv);
$o3 = & newobject("Group", $argv);

print("<P>----클래스 Bank의 상속관계----</P>");
print_chain("Bank");
print("<P>----클래스 Group의 상속관계----</P>");
print_chain("Group"); [/code]
위와 같은 경우의 한 예를 보면 아래와 같이 출력될 것입니다. 여기서 클래스 Bank는 부모클래스 clsArray, clsString, clsDate로부터 상속되었다고 가정하였으며, 클래스 Group는 부모클래스 Check, Serialize로부터 상속되었다고 가정하였습니다.
----클래스 Bank의 상속관계----

clsArray
.clsString
..clsDate
...Bank

----클래스 Group의 상속관계----

Check
.Serialize
..Group

Posted by 방글24
객체지향언어(Object Oriented Programming Language)
C++과 같은 컴파일러가 아닌 스크립트에서 객체지향언어의 클래스를 이용하는 것이 과연 효율적인지, 필요하여 사용한다면 서버의 성능을 필요이상으로 저하시키는 것이 아닌지 등등에 대한 우려로 보통 클래스 사용을 주저하게 됩니다.
그러나 하드웨어가 소프트웨어 발전 속도를 훨씬 앞지르고 있고, 서버 사이드 스크립트도 그 성능이 계속 향상될 것이며, 홈페이지 제작 프로젝트가 점점 다양해지고 대형화되어 가고 있는 시점에서 소프트웨어의 생산성은 상대적으로 점점 중요해 질 수밖에 없지 않을까요? 이러한 면에서 살펴보면 클래스의 사용은 꼭 필요하지 않나 하는 생각이 듭니다.
그러나 PHP에서 클래스를 사용할 때의 문제는 PHP 스크립트의 클래스가 C++이나 smalltalk와 같은 객체지향 프로그래밍 언어와 같이 클래스 구현이 충실하지 못하다는 것입니다. 실험해 본 바에 따르면 생성자(constructor) 실행이 불완전하고, 다중상속(multiple inheritance)과 같은 것을 지원하지 않는 것 같습니다. 자바에서도 다중상속을 지원하지 않기는 하지만 대신 인터페이스 기능이 있어 다중상속 역할을 대신할 수 있지요.
후키라이브러리 개발
"클래스 관리용 라이브러리"(이하 "후키라이브러리")에서는 생성자 실행을 본래의 객체지향언어와 같은 개념을 도입하여 최상위 부모클래스 생성자로부터 최하위 파생클래스 생성자까지 순서대로, 소멸자는 그 반대의 순서로 실행하도록 했으며, 일반적인 다중상속뿐 아니라 동일한 조상클래스(ancestor class)를 가진 클래스의 다중상속도 지원할 수 있도록 작성되었습니다. 또한 생성된 모든 객체에서 공유할 수 있는 정적 데이터멤버를 지원합니다.
지원되는 기능
1. 다중상속(multiple inheritance) 지원
2. 동일한 조상클래스(ancestor class)를 가진 클래스의 다중상속 지원
3. 최상위 클래스로부터 모든 파생클래스의 생성자(constructor)를 순차적으로 실행
4. 최하위 클래스로부터 모든 부모클래스의 소멸자(destructor)를 순차적으로 실행
5. 정적 데이터멤버(static data member) 지원
사용자 함수
1. classdefine : 클래스 정의 함수
2. newobject : 객체 생성 함수
3. classchain : 클래스 상속관계 반환 함수
3개의 함수 중에 실제적으로 클래스를 관리하는데 사용되는 함수는 2개 뿐이며 나머지 한 개의 함수 classchain는 단지 클래스의 상속관계를 알고자 할 때 사용하게 되므로 개발단계에서만 사용하게 됩니다.
예약된 전역변수
후키라이브러리 내에서만 사용되는 전역변수입니다.
$_HWOOKY

Posted by 방글24
PHP 스크립트에서 지원하는 객체지향언어의 클래스 기능을 보완하여 좀 더 편하게 클래스를 개발 및 관리를 할 수 있도록 클래스 관리를 위한 함수를 라이브러리 화하였습니다. 본인도 "후키라이브러리"를 이용하여 프로그램을 개발해 보니 나름대로 편리한 점이 많아 여러분과 공유하고자 이 자리를 마련했습니다.
버그 발견, 개선 요구, 기능 추가......
라이브러리에 버그가 있거나 새로이 개선되기를 바라는 점, 추가되기를 바라는 기능 등이 있으면 "Q&A 게시판"을 이용해 의견을 주세요:-)
후키라이브러리 저작권
파일명    : lib.hwooky.php
버전       : 0.1.0
작성일    : 2002.2.12
사용환경 : >= PHP 4.0.4
제작자    : 황우경(Wookyung Hwang) - 후키(hwooky)
전자우편 : hwooky@phpclass.com
홈페이지 : http://www.phpclass.com
사용권한 :
  본 라이브러리는 공개 라이브러리로 누구나 자유롭게 사용할 수  있으나, 연습용이 아닌 실무에 사용할 때는 혹시 발생할 지  모르는 문제점에 대해 충분히 테스트한 후에 사용하여 주시기  바랍니다. 본 라이브러리의 사용으로 인한 어떠한 피해에도  제작자는 책임을 질 수 없습니다.

Posted by 방글24