phpclass/객체정보2001. 3. 2. 14:10
생성된 객체를 복사하기
이 방법은 여러분이 지금까지 사용하였던 방법입니다.
[code php;gutter:false] <?php

class test {
var $mb;

function test($mb="default") {
$this->mb = $mb;
}
}

$a = new test; // 객체 복사
echo $a->mb;

?> [/code]
위의 예를 통해 생성된 객체가 어떤 경로를 통해 $a 변수에 저장되는지 살펴보기로 하겠습니다.
1. new test
이 부분에 의해 클래스 test에 정의된 생성자 test() 함수가 실행됩니다. 생성자 내용이 모두 처리되면 생성자는 현재 생성된 객체를 나타내는 $this라는 특별한 변수를 되돌려 줍니다. 따라서 "new test"를 처리한 후 되돌려 받게 되는 값은 new 연산자에 의해 생성된 객체를 나타내는 $this라는 변수가 됩니다.
2. $a = new test
"new test"가 되돌려 주는 것이 새로 생성된 객체를 나타내는 $this라는 객체변수이므로 "$a = new test"는 "$a = $this"라고 생각할 수 있습니다. 실제로 이렇게 코딩하면 에러가 나겠지요. 왜냐하면 $this라는 변수는 객체 내에서만 사용되는 특수한 변수이므로 객체 외부에서는 절대로 사용할 수 없습니다. 그냥 이해한다는 면에서 "$a = $this"라고 한다면 이것은 일반적으로 알고 있는 $this라는 변수를 새로운 변수 $a에 할당하는 것이며, 결국 새로운 객체변수 $a를 생성되는 동시에 $this의 내용을 복사하게 된다는 것입니다.
< 객체 복사 >
위 그림에서는 멤버변수만 나타내었습니다. 메소드의 표현 방법은 멤버변수와는 전혀 다르기 때문에 여기서 생략하며 이에 대한 자세한 내용은 메뉴 "핍클래스홈 >> 객체에 관련된 정보"에서 "클래스와 인스턴스" 부분을 읽어 보시기 바랍니다.
3. echo $a->mb
복사된 객체 $a를 통해 멤버변수 $mb에 접근합니다.
생성된 객체를 참조하기
위의 소스 코드에서 클래스 정의 부분은 동일하며 아래 부분만 참조에 의해 수정하면 다음과 같습니다.
[code php;gutter:false] $a = &new test; // 객체 참조
echo $a->mb; [/code]
객체 복사와 같은 방법으로 생성된 객체가 어떤 경로를 통해 $a 변수에 저장되는지 살펴보기로 하겠습니다.
1. new test
이 부분은 객체 복사와 동일합니다.
2. $a = &new test
"new test"가 되돌려 주는 것이 새로 생성된 객체를 나타내는 $this라는 객체변수이므로 "$a = &new test"는 "$a = &$this"라고 생각할 수 있습니다. 이것은 앞장에서 살펴보았듯이 "new test"에 의해 생성된 $this라는 객체변수에 대한 별명(참조)을 하나 만드는 것입니다.
< 객체 참조 >
3. echo $a->mb
이 부분은 객체 복사와 동일합니다.
메모리 자원 사용
생성자에 있는 $this의 참조를 사용하기 위해서는 참조할당(reference assignment)을 사용하여야 하며 그렇지 않으면 두 개의 서로 다른 객체를 가지게 될 것입니다.
$this 라는 것은 "new test"를 수행할 때 생성자에서 되돌려 주는 $this를 의미합니다. new 연산자로 생성된 객체를 복사로 받으나 아니면 참조로 받으나 실행에는 전혀 차이가 없습니다. 차이가 있다면 서버 자원(resource)을 얼마나 효율적으로 사용하느냐는 것이지요. 첫번째 처럼 객체를 복사하게 되면 메모리 0x6000에 있는 객체는 페이지가 종료될 때까지 전혀 사용하지도 못하면서 서버 자원만 낭비하고 있는 것이지요. 하지만 객체를 참조하게 되면 생성된 객체를 $b에서 그대로 사용하기 때문에 자원 낭비가 전혀 없게 됩니다.
객체 복사할 때의 메모리
< 심볼 테이블 >
변수명 변수값이 저장된 메모리 주소 설명
$this 0x6000 원본
$a 0x7000 복사

객체 참조할 때의 메모리

< 심볼 테이블 >
변수명 변수값이 저장된 메모리 주소 설명
$this 0x6000 원본
$a 0x6000 참조
메모리 자원을 사용하는데 있어 참조의 장점을 개념상 설명을 하였습니다만 PHP가 실제로 이 개념대로 구현된 것 같지는 않습니다. 정확한 것은 소스를 분석해 보아야 하겠으나 문서상의 설명으로 보면 객체 복사가 오히려 객체 참조보다 수행속도가 미세하나마 빠른 것으로 볼 때 PHP의 참조에 관련된 내부 구현 방식이 개념상 자바나 C++과는 다소 다른 것 같습니다. 따라서 현 시점(PHP 4.0.4 기준)에서 볼 때는 객체 참조가 꼭 요구되지 않는다면 객체 복사를 이용하는 것이 나을 것 같습니다. 그러나 향후 이 문제에 대하여는 PHP가 개선이 있어야 할 것으로 보입니다. 그러니 앞으로 객체 참조가 더 개선될 것을 대비하고 코드의 재사용을 고려하고 객체 복사와 객체 참조의 실행속도가 거의 차이가 없다는 것을 염두에 둔다면 그냥 객체 참조를 사용하는 것이 괜찮으리라 봅니다.
[Zend 엔진 2.0에서의 객체] Zend 엔진 1.0에서는 객체를 전달할 때 기본적으로 복사되어집니다. 그러나 Zend 엔진 2.0부터는 기본적으로 참조로 전달되어 집니다. 즉, 객체를 전달할 때는 참조기호 &가 필요없어진 것이지요. 그러니 PHP3 또는 Zend 엔진 1.0가 탑재된 PHP4로 작성된 문서에서 특별한 문제만 없다면 향후 호환성을 위하여 객체를 전달할 때는 참조기호 &를 사용하지 말기를 바랍니다.

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

{참조}4.참조 반환  (0) 2001.03.02
{참조}3.참조에 의한 전달  (0) 2001.03.02
{참조}1.참조변수의 생성  (0) 2001.03.02
{추상클래스}6.세셔너 확장  (0) 2000.12.28
{추상클래스}5.세셔너 분석  (0) 2000.12.28
Posted by 방글24
phpclass/객체정보2001. 3. 2. 13:59
C++에서 사용하던 참조(reference)와 같은 기능을 PHP4에서 제공합니다. 참조는 객체를 사용할 때 필수적인 기능이므로 꼭 익혀두시기 바랍니다.
비유에 의한 설명
명선이라는 여자 아이가 살고 있습니다. 그런데 그 아이의 마음씨가 얼마나 좋은지 사람들이 명선이에게 천사라는 별명을 붙여주었습니다. 제가 천사같은 명선이에게 1000원을 주었다고 할 때 명선이에게 1000원을 주었지만 천사에게도 1000원을 준 것과 동일합니다.
< 본명과 별명 >
PHP에서도 이와 같이 특정 변수에 별명을 붙여 사용할 수 있습니다. PHP에서 이와 같이 별명을 만들 수 있는 기능을 참조(reference)라고 하며 PHP4.0.4부터 본격적으로 제공되기 시작했습니다.
< 변수 $a와 참조 $b >
이러한 별명 즉 참조변수를 생성하기 위해서는 아래와 같이 & 심볼을 사용합니다.
[code php;gutter:false] $b = &$a; // 변수 $a의 참조 $b를 생성
$a = 1000; [/code]
참조란 다른 이름을 가지고 동일한 변수에 접근할 수 있도록 하는 것입니다. C 또는 C++의 포인터와는 다르며 C++에서 새로이 추가된 참조와 같이 앞에서 정의된 변수에 대한 이름(변수명)의 대용으로 작용하는 이름입니다. 즉, 앞서 정의된 변수명에 대한 별명입니다. 따라서 이들 둘은 모두 같은 값, 같은 메모리의 위치를 참조합니다.
참조와 복사
참조가 하나의 변수를 두 개의 이름(변수명)으로 불려지는 것인 반면에 복사는 완전히 독립된 두 개의 변수를 만들게 됩니다.
예를 들어 $a으로 하여금 $b 변수를 참조하도록 만든다면 $a와 $b는 서로 다른 이름을 사용하기는 하지만 $a와 $b는 둘 다 동일한 장소(메모리 위치)를 가리키기 때문에 동일한 내용을 다루게 됩니다.
그러나 $a으로 하여금 $c 변수에 복사하게 되면 처음 복사할 때만 그 내용이 같을 뿐이며 이 후에 $a와 $c는 전혀 관계없이 동작하는 별개의 변수가 됩니다.
[code php;gutter:false] $a = 1000; // 변수 $a의 생성
$b = &$a; // $b는 $a의 참조(별명)
$c = $a; // $c는 $a의 복사 [/code]
< 참조와 복사 >
변수명를 관리하는 심볼 테이블과 변수값이 저장되어 있는 메모리 상태를 살펴보면 다음과 같습니다. 여기서 표현된 것은 설명을 위해 개념적으로 나타낸 것이며 정확한 것은 아닙니다.
< 심볼 테이블 >
변수명 변수값이 저장된 메모리 주소 설명
$a 0x6000 원본
$b 0x6000 참조
$c 0x7000 복사
참조와 포인터
C 또는 C++에서 자주 보게 되는 포인터와 비교해보죠. 사실 참조로 구현할 수 있는 것은 포인터로 모두 구현할 수 있습니다. 그러나 양쪽이 모두 동일한 효과를 얻더라도 소스코드의 가독성를 보면 참조가 훨씬 명료합니다. PHP가 포인터를 지원하지 않으므로 여기서 비교할 필요가 없을 지도 모르겠으나 그냥 참고삼아 보시기 바랍니다. 만약 PHP에서 포인터를 지원한다면 위의 심볼 테이블에서 메모리 주소 0x6000 또는 0x7000 이라는 숫자를 직접 얻을 수 있겠지요.
아래 예는 C++로 작성된 코드로 함수의 매개변수로 전달된 두 변수를 교환하는 방법입니다.
[code c;gutter:false] void swap(int & a, int & b) { // 참조를 사용
int temp;

temp = a; // 변수의 값으로 a, b를 사용
a = b;
b = temp;
}

void swap(int * pa, int * pb) { // 포인터를 사용
int temp;

temp = *pa; // 변수의 값으로 *pa, *pb를 사용
*pa = *pb;
*pb = temp;
} [/code]
위에서 보는 바와 같이 참조를 사용하면 포인터를 사용할 때보다 코드를 훨씬 쉽게 이해할 수 있습니다. 포인터가 일반적으로 훨씬 강력하고 폭넓은 능력을 발휘하기는 하지만 잘못 사용하면 시스템을 불안하게 하기 때문에 안정성이 우선인 웹프로그래밍 언어에서 포인터를 지원하기는 어려울 것입니다. 하지만 원본을 사용범위(scope)가 다른 곳에서 또는 다른 이름으로 안전하고, 편하게 다루게 해주는 참조가 있기 때문에 개발자는 포인터없이도 별 어려움없이 원하는 기능을 구현할 수 있을 것입니다.
자바에서의 객체 참조
자바에서는 PHP 또는 C++에서와는 달리 객체를 변수에 할당하거나, 객체를 매개변수로 메소드에 전달할 때, 전달되는 것은 이러한 객체의 참조(레퍼런스)이지 객체의 복사본이 아닙니다.
[code java;gutter:false] import java.awt.Point;

class ReferencesTest {
public static void main (String args[]) {
Point pt1, pt2;
pt1 = new Point(100, 100);
pt2 = pt1;

pt1.x = 200;
pt1.y = 200;
system.out.println("Point1: " + pt1.x + ", " + pt1.y);
system.out.println("Point2: " + pt2.x + ", " + pt2.y);
}
} [/code]
출력결과는 아래와 같습니다.
Point1: 200, 200
Point2: 200, 200
pt2 의 x와 y 인스턴스 변수 또한 바뀌었습니다. pt1의 값을 pt2로 할당했을 때, 정확히 말하자면 pt2로부터 pt1도 똑같이 참조하는 레퍼런스를 생성한 것입니다. pt2가 참조하는 객체를 바꾸게 되면, pt1이 가리키는 객체 또한 바뀌게 됩니다. 이들은 같은 객체를 참조하기 때문입니다.
만일 pt1과 pt2가 각각의 분리된 객체를 가리키게 하기를 원한다면 pt2 = pt1 대신에 pt2 = new Point(100, 100)을 사용하여야 합니다.
함수의 매개변수로 사용되는 참조
참조를 자주 사용하는 것 중에 하나가 함수에서의 매개변수입니다. 참조를 매개변수로 사용하면 그 함수는 복사본 대신에 자료의 원본을 가지고 작업을 합니다. 매개변수값이 큰 사이즈의 문자열 또는 객체일 때 복사본 가지고 작업한다면 우선 복사하는데 많은 시간이 소요될 것입니다. 또 작업한 내용을 되돌려 주어야 한다면 돌려주는데 또 시간이 많이 소요될 것입니다. 이럴 때는 처음부터 원본가지고 작업하면 유리하겠지요. 참조 기능 중 유일하게 이 부분만(일부이기는 하지만) PHP3에서도 제공되어 왔습니다. 자세한 것은 "참조에 의한 전달"을 보시기 바랍니다.
PHP에서 지원하는 참조 관련 기능
참조에 의한 함수 호출(call by reference)를 제외한 대부분의 기능은 PHP 4.0.4부터 가능합니다. 이러한 참조기능 - 참조변수 생성, 참조에 의한 함수호출 및 반환 - 은 C++의 참조를 모델로 구현되어 있습니다. 따라서 C++에서 참조를 사용하시던 분은 별 어려움없이 PHP 참조를 사용하시리라 봅니다.

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

{참조}3.참조에 의한 전달  (0) 2001.03.02
{참조}2.객체생성에서의 참조  (0) 2001.03.02
{추상클래스}6.세셔너 확장  (0) 2000.12.28
{추상클래스}5.세셔너 분석  (0) 2000.12.28
{추상클래스}4.PHP  (0) 2000.12.28
Posted by 방글24
phpclass/객체정보2000. 12. 28. 15:13
저장 매체의 변경
세셔너 함수를 작성하는데 추상클래스를 이용하였으면, 그 이점이 있어야 할 것 아닙니까? 그 한 예로 공개된 세셔너 함수에서 사용하고 있는 파일 시스템 대신에 데이터베이스를 이용하여 보도록 하겠습니다. 다른 클래스는 건드릴 필요가 전혀 없으며 오로지 클래스 sessStaticDevice 만 아래에 있는 클래스로 대체시키면 됩니다.
[code php;gutter:false] class sessStaticDevice extends sessStaticID {
var $startedPath;
var $BaseClass = "baseDbsql";
var $BaseObject;

function sessStaticDevice() {
$this->sessStaticID();
$this->Path = "Sessioner";
}

function _sessStaticDevice() {
$this->_sessStaticID();
}

function prvStartedDevice($path) {
$this->startedPath = $path;
}

function prvInitBase() {
if (!is_object($this->BaseObject)) {
$base = $this->BaseClass;
$this->BaseObject = new $base;
}
}

function prvGc() {
$this->BaseObject->query("SELECT id FROM "
.$this->startedPath
." WHERE lastused < "
.(time() - $this->Maxlifetime));
while ($record=$this->BaseObject->next_record())
$id_arr[] = $record["id"];
if (is_array($id_arr)) {
reset($id_arr);
while (list(,$id)=each($id_arr)) {
$this->prvOnEnd();
$this->BaseObject->query("DELETE FROM "
.$this->startedPath." WHERE id='$id'");
}
}
list($rows,$fields) = $this->BaseObject->query(
"SELECT id FROM ".$this->startedPath);
return $rows;
}

function prvRead() {
$this->BaseObject->query("SELECT value, lastused FROM "
.$this->startedPath." WHERE id='".$this->ID."'");

if ($record=$this->BaseObject->next_record())
return stripslashes($record["value"]);
return false;
}

function prvWrite($value) {
$this->BaseObject->query("REPLACE INTO "
.$this->startedPath." (id, value, lastused) "
."VALUES ('".$this->ID."', '"
.addslashes($value)."', ".time().")");
}

function prvDestroyDevice() {
$this->BaseObject->query("DELETE FROM "
.$this->startedPath." WHERE id='".$this->ID."'");
}
} [/code]
세셔너 데이터 저장용 테이블 생성
데이터베이스를 이용하기 때문에 먼저 세션 데이터를 저장할 테이블을 생성하여야 합니다. 아래는 MySQL 데이터베이스의 테이블을 생성하기 위한 SQL 문을 나타내었습니다.
[code sql;gutter:false] CREATE TABLE Sessioner (
id varchar(32) not null PRIMARY KEY,
value text not null,
lastused int(8)
); [/code]
session_start() 함수 수정
또 하나 추가로 처리하여야 할 것은 데이터베이스를 세셔너 함수 내에서 사용하기 위한 함수가 하나 추가되었습니다. 그것은 prvInitBase() 함수이며, 이 함수에서는 클래스 $sessStatic 내에서 사용할 데이터베이스 객체를 생성하는 역할을 합니다. session_start() 함수에서 스크립트 실행 후 단 한번만 실행시켜 주면 됩니다.
[code php;gutter:false] function session_start() {
//
// 데이터베이스를 이용하기 위해 새로 추가된 부분
//
$GLOBALS["sessStatic"]->prvInitBase();
return $GLOBALS["sessStatic"]->prvStart();
} [/code]
미니디비 파일 인클루드 및 객체 생성
데이터베이스 예제는 제가 공개한 미니디비를 이용하였기 때문에, 사용자 프로그램에서 세셔너 파일을 인클루드 하기 전에 미니디비 파일을 인클루드하여야 하며, session_start() 함수를 실행하기 전에 미니디비 클래스를 이용하여 데이터베이스 객체를 생성하여야 합니다. 이 때 객체명은 사용자가 임의로 지정할 수 있습니다.
[code php;gutter:false] <?php

require("./minidb/class.mysql.php");
require("./sessioner/sessbase.php");

$base = new baseDbsql("호스트명","사용자ID","비밀번호","디비명");

session_start();

......

?> [/code]
"......" 부분은 이미 공개한 세셔너함수-0.2.0 또는 0.2.1과 사용방법이 동일합니다. 물론 PHP4 세션함수 사용법과도 동일합니다. 데이터베이스용 세셔너함수에 대한 자료는 파일로 공개하지 않겠습니다. 필요한 것은 이곳에 모두 있기 때문에 여러분이 잘 이해하신 후 사용하시면 제대로 동작할 것입니다.

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

{참조}2.객체생성에서의 참조  (0) 2001.03.02
{참조}1.참조변수의 생성  (0) 2001.03.02
{추상클래스}5.세셔너 분석  (0) 2000.12.28
{추상클래스}4.PHP  (0) 2000.12.28
{추상클래스}3.자바  (0) 2000.12.28
Posted by 방글24
phpclass/객체정보2000. 12. 28. 15:04
세셔너함수(0.2.0, 0.2.1)의 설계개념
세셔너함수를 정의한 파일의 소스코드를 살펴보면 세셔너 함수들이 내부적으로 호출하고 있는 객체를 생성하기 위한 클래스가 다소 장황하게 작성되어 있습니다. 객체지향프로그래밍의 추상클래스라는 개념을 도입하여 작성되어 있어서 그렇게 보일 것입니다. 그러나 추상클래스 개념을 잘 활용한다면 많은 이점을 가져다 줄 것입니다.
사용자 함수의 구조
사용자가 접근할 수 있는 세셔너 함수들은 모두 전역함수를 이용하여 작성되어 있으나, 세셔너 함수가 내부적으로 사용하는 함수들은 sessStatic 라는 클래스에서 생성된 $sessStatic라는 객체를 이용하여 구현되었습니다.
[code php;gutter:false] function session_start() {
return $GLOBALS["sessStatic"]->prvStart();
}

function session_destroy() {
return $GLOBALS["sessStatic"]->prvDestroy();
}

function session_register($varname) {
return $GLOBALS["sessStatic"]->prvRegister($varname);
}

function session_unregister($varname) {
return $GLOBALS["sessStatic"]->prvUnregister($varname);
}

.
.
. [/code]
sessStatic 클래스의 구성
< 세셔너 함수의 구성(클래스 설계 및 구현) >
추상클래스 sessStaticID, sessStaticDevice, sessStaticEvent가 최상위 추상클래스 sessStaticAbstract로부터 각각 파생되도록 설계되었으며, 일반클래스 sessStatic가 sessStaticID, sessStaticDevice, sessStaticEvent로부터 다중 상속되도록 설계되어 있습니다. 일반클래스 sessStatic 에 이르러서는 상위클래스에 있는 모든 추상함수가 구현되므로 객체를 생성할 수 있게 되며 세셔너 함수 내에서 $sessStatic 라는 객체를 생성하여 세셔너 함수에서 접근할 수 있도록 하였습니다. PHP에서 다중상속을 지원하지 않으므로 아래와 같이 연속적인 단일상속으로 구현하였습니다.
[code php;gutter:false] class sessStaticAbstract { // 최상위 추상클래스
......
}

class sessStaticID extends sessStaticAbstract { // 세션ID 관리
......
}

class sessStaticDevice extends sessStaticID { // 저장매체 관리
......
}

class sessStaticEvent extends sessStaticDevice { // 이벤트 처리
......
}

class sessStatic extends sessStaticEvent { // 최하위 일반클래스
......
}

$sessStatic = new sessStatic; [/code]
sessStaticAbstract 클래스
추상클래스로 작성된 sessStaticAbstract에는 일반함수와 추상함수가 혼재되어 있습니다. 세션ID 관리함수, 저장매체 관리함수, 이벤트 처리 함수는 추상함수로 작성되어 있어서 하위클래스에서 이들 함수의 몸체가 구현되어 있습니다.
[code php;gutter:false] //
// 저장매체 관리함수
//
function prvRead() {}
function prvWrite($value) {}
function prvDestroyDevice() {}
function prvGc() {}
function prvStartedDevice($path) {}

//
// 이벤트 처리 함수
//
function prvOnStart() {}
function prvOnEnd() {}

//
// 세션ID 관리함수
//
function prvGetID() {}
function prvSetID($id) {}
function prvStartedID($name) {} [/code]
이와 같이 추상함수의 몸체에는 어떠한 코드도 정의되어 있지 않으며, 이 함수들의 하위클래스에서 그 동작이 구체적으로 명시됩니다.
추상클래스로 상속되는 하위클래스
추상클래스 sessStaticAbstract로부터 상속받는 하위클래스 sessStaticID, sessStaticDevice, sessStaticEvent 는 모두 부모클래스의 모든 추상함수를 구현하지 않기 때문에 일부함수가 계속 추상함수로 남게됩니다. 따라서 이들 하위클래스 모두 여전히 추상클래스라고 할 수 있습니다.
세셔너 함수 소스 코드를 보면 클래스 sessStaticEvent에 prvOnStart(), prvOnEnd()가 빠져 있을 것입니다. 세셔너 함수는 PHP4 세션함수와의 호환성을 목적으로 하기 때문에 PHP4 세션함수에 없는 이벤트 함수를 포함시킬 수 없었습니다. 이것은 객체지향프로그래밍 이론으로 보면 이 부분에서 에러가 발생할 것입니다. PHP 스크립트에서야 이런 개념이 없으니까 두리뭉실 넘어가고 있죠. 아래는 이벤트 함수를 구현한 완전한 StaticEvent 클래스입니다. 참조바랍니다.
[code php;gutter:false] class sessStaticEvent extends sessStaticDevice {
var $EventPath = ".";

function sessStaticEvent() {
$this->sessStaticDevice();
$this->prvEventFunc();
}

function _sessStaticEvent() {
$this->_sessStaticDevice();
}

function prvEventFunc() {
$eventfile = $this->EventPath."/event.sessioner.php";
clearstatcache();
if (is_file($eventfile)
&& !function_exists("sessioner_onStart")
&& !function_exists("sessioner_onEnd")) {
include($eventfile);
}
}

function prvOnStart() {
if (function_exists("sessioner_onStart"))
sessioner_onStart();
}

function prvOnEnd() {
if (function_exists("sessioner_onEnd"))
sessioner_onEnd();
}
} [/code]
일반클래스로 정의되는 최하위클래스 sessStatic
마지막으로 파생된 클래스 sessStatic 에 와서야 비로서 모든 추상함수가 구현됩니다. 세셔너함수 소스코드를 보면 실제로는 sessStaticEvent 클래스에서 모든 추상함수가 구현되지만 향후 세셔너가 확장되면서 또다른 추상함수가 추가될 수 있으며 그 때는 sessStaticEvent 클래스의 하위클래스에서 추가된 추상함수를 구현할 수 있기 때문에 설계 개념상 sessStaticEvent를 추상클래스로 분류하였습니다. 혼동없기를 바랍니다.
sessStatic 를 제외한 모든 상위클래스들은 추상클래스이므로 객체를 생성할 수 없으며 모든 추상함수를 구현한 일반클래스로 작성된 sessStatic를 이용하여 객체를 생성할 수 있습니다. PHP에서는 추상클래스 개념이 없으므로 객체를 생성할 수 있으나, 동작은 제대로 하지 않을 것입니다. 여기서 객체를 생성할 수 없다고 한 것은 추상클래스 개념으로 보았을 때 그렇다는 것으로 객체를 생성해서는 안된다는 것을 의미합니다. 세셔너 함수 파일 최하단에 보면 sessStatic 클래스를 이용하여 객체를 생성하여 내부적으로 사용하고 있습니다.
[code php;gutter:false] $sessStatic = new sessStatic; [/code]

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

{참조}1.참조변수의 생성  (0) 2001.03.02
{추상클래스}6.세셔너 확장  (0) 2000.12.28
{추상클래스}4.PHP  (0) 2000.12.28
{추상클래스}3.자바  (0) 2000.12.28
{추상클래스}2.C++  (0) 2000.12.28
Posted by 방글24
phpclass/객체정보2000. 12. 28. 15:03
추상함수(???)
PHP에는 추상함수나 추상클래스라는 개념이 없습니다. 있다고 가정하고 추상함수와 추상클래스를 흉내내어 보겠습니다. 아래와 같이 추상함수를 선언합니다.
[code php;gutter:false] function breathe() {} // 추상함수(메소드의 몸체는 없음) [/code]
추상클래스(???) 정의
클래스에 하나 이상의 추상함수가 있다면 그것을 추상클래스라고 가정하겠습니다.
[code php;gutter:false] //
// 추상클래스 animal
//
class animal {
function breathe() {} // 추상함수
} [/code]
추상함수의 오버라이드
하위클래스를 정의할 때는 추상함수 breathe()를 오버라이드해야 합니다.
[code php;gutter:false] //
// 추상클래스 animal로부터 파생된 일반클래스 fish
//
class fish extends animal {
//
// 추상함수 breathe()의 오버라이드
//
function breathe() {
print "Bubbling...\n";
}
} [/code]
추상클래스 예제
[code php;gutter:false] //
// 추상클래스 animal
//
class animal {
function eat() { // 일반메소드
print "Eating...\n";
}
function breathe() {} // 추상함수
}

//
// 추상클래스 animal로부터 파생된 일반클래스 fish
//
class fish extends animal {
//
// 추상함수 breathe()의 오버라이드
//
function breathe() {
print "Bubbling...\n";
}
}

//
// 프로그램의 최초 진입점
//
$my_fish = new fish;
$my_fish->breathe(); [/code]
이 경우에 프로그램은 클래스 fish에 정의된 breathe()함수를 수행하게 됩니다. 따라서 "Bubbling..."이 화면에 표시됩니다.

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

{추상클래스}6.세셔너 확장  (0) 2000.12.28
{추상클래스}5.세셔너 분석  (0) 2000.12.28
{추상클래스}3.자바  (0) 2000.12.28
{추상클래스}2.C++  (0) 2000.12.28
{추상클래스}1.개요  (0) 2000.12.28
Posted by 방글24
phpclass/객체정보2000. 12. 28. 15:02
추상메소드
추상메소드는 실제로 동작하는 부분이 없고 메소드 선언부만 있는 것을 말합니다. 추상메소드는 메소드앞에 abstract 키워드를 사용하여 일반메소드와 구별합니다. 그리고 생성자와 클래스 메소드 그리고 private 로 선언한 메소드는 추상메소드가 될 수없습니다.
[code java;gutter:false] abstract public void breathe(); // 추상메소드(메소드의 몸체는 없음) [/code]
추상클래스 정의
추상클래스는 추상메소드를 포함할 수 있고, 추상메소드를 포함하는 클래스는 반드시 추상클래스로 선언되어야 합니다. 추상클래스는 추상메소드와 마찬가지로 해당 클래스 앞에 abstract 키워드를 사용하여 다음과 같이 선언할 수 있습니다.
[code java;gutter:false] //
// 추상클래스 Animal
//
abstract class Animal {
abstract public void breathe(); // 추상메소드
} [/code]
추상메소드의 오버라이드
추상클래스는 반드시 하위 클래스를 가지며, 추상클래스를 상속받은 하위클래스는 반드시 상위클래스의 추상메소드를 모두 재정의 하여야 합니다.
[code java;gutter:false] //
// 추상클래스 Animal로부터 파생된 일반클래스 Fish
//
class Fish extends Animal {
//
// 추상메소드 breathe()의 오버라이드
// 이때에 항상 public을 붙여서 사용해야 한다.
//
public void breathe() {
System.out.println("Bubbling...");
}
} [/code]
추상클래스 예제
[code java;gutter:false] //
// 추상클래스 Animal
//
abstract class Animal {
public void eat() { // 일반메소드
System.out.println("Eating...");
}
abstract public void breathe(); // 추상메소드
}

//
// 추상클래스 Animal로부터 파생된 일반클래스 Fish
//
class Fish extends Animal {
//
// 추상메소드 breathe()의 오버라이드
//
public void breathe() {
System.out.println("Bubbling...");
}

//
// 프로그램의 최초 진입점
//
public static void main(String args[]) {
Fish my_fish = new Fish();
my_fish.breathe();
}
} [/code]
이 경우에 프로그램은 클래스 Fish에 정의된 breathe()함수를 수행하게 됩니다. 따라서 "Bubbling..."이 화면에 표시됩니다.
자바에서의 추상클래스에 대한 좀 더 자세한 정보는 관련 서적을 참고하시기 바랍니다.

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

{추상클래스}6.세셔너 확장  (0) 2000.12.28
{추상클래스}5.세셔너 분석  (0) 2000.12.28
{추상클래스}4.PHP  (0) 2000.12.28
{추상클래스}2.C++  (0) 2000.12.28
{추상클래스}1.개요  (0) 2000.12.28
Posted by 방글24
phpclass/객체정보2000. 12. 28. 15:01
순수가상함수(pure virtual function)
C++ 에서 함수 몸체가 없이 정의되는 함수이며 몸체 부분을 =0으로 지정하여야 합니다. 순수가상함수가 포함된 클래스를 추상클래스(Abstract Class)라고 하며, 이 추상클래스로는 직접 객체를 만들 수 없고 상속을 통해 다른 클래스를 생성하는 데 사용합니다. 추상클래스로부터 상속받은 클래스는 반드시 순수가상함수를 구현해야 합니다.
[code c;gutter:false] virtual void breathe(void) = 0; // 순수가상함수(메소드의 몸체는 없음) [/code]
추상클래스 정의
자바에서처럼 추상클래스를 구분하는 abstract와 같은 키워드는 없으며, 단지 클래스에 하나 이상의 순수가상함수가 있다면 그것을 추상클래스라고 합니다.
[code c;gutter:false] //
// 추상클래스 animal
//
class animal {
public:
virtual void breathe(void) = 0; // 순수가상함수
}; [/code]
순수가상함수의 오버라이드
하위클래스를 정의할 때는 순수가상함수 breathe()를 오버라이드해야 합니다. C++는 객체를 설정할 때 순수가상함수를 오버라이드하지 않는 것을 에러로 여깁니다. 즉, 한 클래스가 하나나 그 이상의 순수가상함수를 가진다면 그 클래스의 객체를 생성할 수 없습니다.
[code c;gutter:false] //
// 추상클래스 animal로부터 파생된 일반클래스 fish
//
class fish : public animal {
public:
void breathe(void);
} my_fish;

//
// 순수가상함수 breathe()의 오버라이드
//
void fish::breathe(void) {
cout << "Bubbling...\n";
} [/code]
추상클래스 예제
[code c;gutter:false] #include <iostream.h>
#include <conio.h>

//
// 추상클래스 animal
//
class animal {
public:
void eat(void); // 일반메소드
virtual void breathe(void) = 0; // 순수가상함수
};

//
// 추상클래스 animal로부터 파생된 일반클래스 fish
//
class fish : public animal {
public:
void breathe(void);
} my_fish;

//
// 모든 멤버함수 선언
//
void animal::eat(void) {
cout << "Eating...\n";
}

void fish::breathe(void) {
cout << "Bubbling...\n";
}

//
// 프로그램의 최초 진입점
//
main() {
my_fish.breathe();
getche();
return 0;
} [/code]
이 경우에 프로그램은 fish::breathe()함수를 수행하게 됩니다. 따라서 "Bubbling..."이 화면에 표시됩니다.
C++에서의 추상클래스에 대한 좀 더 자세한 정보는 관련 서적을 참고하시기 바랍니다.

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

{추상클래스}6.세셔너 확장  (0) 2000.12.28
{추상클래스}5.세셔너 분석  (0) 2000.12.28
{추상클래스}4.PHP  (0) 2000.12.28
{추상클래스}3.자바  (0) 2000.12.28
{추상클래스}1.개요  (0) 2000.12.28
Posted by 방글24
phpclass/객체정보2000. 12. 28. 14:58
메뉴 "객체지향언어로서의 PHP"에 포함시켜도 되는 주제이지만, 내용의 분량이 많아 별도의 메뉴로 분리하였습니다. 제가 공개한 세셔너함수-0.2.0을 작성하면서 도입된 객체지향프로그래밍 이론입니다.
여기에 있는 내용들은 관련 웹사이트나 관련 서적에 있는 내용을 정리(짜집기)한 것입니다.
추상클래스(abstract class)
추상클래스는 추상적인 클래스로써 그 구현이 덜 되었거나 또는 아직은 미완성 클래스이므로 실제 인스턴스(또는 객체)를 생성할 수 없도록 한 클래스입니다. 다시 말해서, 추상클래스는 객체가 가지는 특성들을 추상화시켜 놓았을 뿐 아직 구체화 시키지 못한 클래스이므로, 이 추상클래스를 상속하는 하위클래스에서 좀 더 구체화 시키도록 하는 것입니다. 따라서, 추상클래스를 상위클래스로 하여 상속하는 하위클래스는 추상클래스인 상위클래스에서 완전히 구현하지 못한 부분들을 완전하게 구현해 주어야만 하위클래스에 대한 객체 생성이 가능하고, 그렇지 못할 경우 하위클래스는 상위클래스인 추상클래스와 같이 미완성이므로 자체적으로 객체를 생성할 수 없고, 이 하위클래스는 다시 추상클래스가 됩니다.
추상클래스는 객체 지향 프로그램에서 하위클래스들의 공통된 특성을 추출하여 묘사하기 위한 클래스로, 클래스 자체가 너무 일반적인 특성을 가지기 때문에 객체를 생성하여 실제로 사용하기에 부적당한 클래스로, 디자인의 편의를 위해서 사용됩니다. 추상클래스의 일반적인 특성을 하위클래스에서 좀 더 덧붙여 실제 사물을 표현할 수 있기 때문에 추상클래스 그 자체로는 쓸모가 없지만 파생을 할 경우는 쓸모가 있습니다.
추상함수(abstract function)
추상클래스에는 연관된 하위클래스들의 공통데이터 구조, 즉 변수들을 정의하고, 함수중 일부는 완전히 구현하지 않고 프로토타입만 정의합니다. 이와 같이 추상클래스에는 함수 몸체가 없이 정의되는 함수를 멤버로 가지게 됩니다. 이것은 필요한 기능을 지금 당장 함수로 구현할 수 없을 때 일단 정의만 해두고 내용은 나중에(하위클래스에서) 채워넣고 사용하겠다는 의미입니다. 이러한 몸체가 없이 정의되는 함수를 C++에서는 순수가상함수(pure virtual function)라고 하고 자바에서는 추상메소드(abstract method)라고 합니다. 여기서는 앞으로 순수가상함수 또는 추상메소드를 추상함수라 통칭하겠습니다.
추상함수를 포함하고 있는 추상클래스를 상속하는 하위클래스는 추상클래스가 갖고 있는 모든 추상함수를 구현하여 주어야 합니다. 그럴 경우, 하위클래스는 일반클래스처럼 사용할 수 있고, 인스턴스의 생성도 가능하지만, 추상함수를 모두 구현해 주지 못한 경우에는 하위클래스도 구현이 완전히 이루어지지 않은 추상함수를 포함하게 되므로 추상클래스가 됩니다.
추상클래스의 예
추상클래스의 아주 좋은 예로 그래픽 화면 상의 한 좌표를 가지는 Position 클래스를 들 수 있습니다.
[code php;gutter:false] class Position {
var $px, $py;
} [/code]
이 클래스는 위치만을 가지기 때문에 어떠한 그래픽 요소도 표현할 수가 없습니다. 가장 간단한 그래픽 요소인 점조차도 색상을 지정할 능력이 없기 때문에 표현이 불가능하며 단지 위치만을 가질 뿐입니다. 하지만 이 클래스는 모든 그래픽 요소에서 공통된 요소인 위치를 가지므로 파생을 할 경우는 하위클래스 자체가 유용하게 사용될 수 있습니다. 점을 나타내는 Point 클래스를 이 클래스로부터 파생시켜 색상을 나타내는 데이터 멤버만 덧붙이면 되며 원은 색상과, 반지름을 덧붙이고, 선은 끝점의 좌표와 색상을 덧붙이면 됩니다. 그외의 다른 그래픽 요소들도 Position 클래스로부터 파생시켜 나갈 수 있습니다.
추상클래스란 이렇게 파생을 목적으로 만들어지는 부모클래스이며 추상클래스의 멤버 함수는 객체를 가지지 않기 때문에 코드를 가질 필요가 없습니다. 단 하위클래스에서 멤버 함수를 재정의(overriding)하여 쓸 수 있도록 추상함수로 멤버 함수를 정의해주기만 하면 됩니다.
추상클래스의 특징
  • 추상함수를 갖는 클래스는 자동으로 추상클래스가 됩니다. 추상클래스는 최소한 한 개 이상의 추상함수를 가져야 합니다.
  • 추상클래스로부터 인스턴스 객체를 생성할 수는 없으며, 반드시 하위클래스가 존재합니다.
  • 추상클래스의 하위클래스는 상위클래스의 추상함수를 구현해주기만 하면 해당 하위클래스의 인스턴스 객체를 생성해 줄 수 있습니다.
  • 추상클래스의 하위클래스가 추상클래스로부터 상속받은 모든 추상함수를 구현해주지 않는 한 하위클래스 자신도 추상클래스가 됩니다.

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

{추상클래스}6.세셔너 확장  (0) 2000.12.28
{추상클래스}5.세셔너 분석  (0) 2000.12.28
{추상클래스}4.PHP  (0) 2000.12.28
{추상클래스}3.자바  (0) 2000.12.28
{추상클래스}2.C++  (0) 2000.12.28
Posted by 방글24