phpclass/클래스활용2000. 6. 12. 14:53
소멸자란?
객체지향언어에서는 생성된 객체가 사라질 때 수행해야 할 일을 소멸자(destructor) 내에서 처리하도록 되어 있습니다. 클래스가 상속관계에 있을 때에 각 클래스에 있는 소멸자의 실행순서는 생성자와 반대로 동작하게 됩니다. 즉, 파생클래스의 소멸자가 먼저 실행된 다음에 부모클래스의 소멸자가 순서대로 실행됩니다.
PHP3에서의 소멸자
PHP3에서는 소멸자를 지원하지 않습니다. 따라서 객체를 제거할 때에 수행해야 할 함수가 있다면 이를 수행할 수 있는 함수를 아래와 같이 작성할 수 있습니다.
[code php;gutter:false] <?php

class test {
function destructor() {
// 여기에 객체를 제거할 때 수행해야할 기능을 추가
}
}

$obj = new test;
.
.
.
$obj->destructor();
unset($obj);
.
.
.

?> [/code]
unset() 함수에 의해 객체는 메모리에서 제거될 것입니다. 그러나 스크립트 종료 직전에는 unset() 함수를 사용할 필요는 없습니다. 스크립트의 실행이 종료되면 객체들도 자동적으로 제거됩니다.
PHP3에서의 소멸자 구현
객체 생성할 때 register_shutdown_function() 함수를 이용해 전역함수를 작성한 후 이 전역함수 내에서 스크립트가 종료될 때 수행될 최하위 파생클래스에 대한 소멸자를 실행하세요.
[code php;gutter:false] <?php

function __register_destructor() {
global $obj;
$obj->testext_destructor();
}

class test {
// 생성자
function test() {
// 여기에 객체를 생성할 때 수행해야할 기능을 추가
}

// 사용자 정의 소멸자
function test_destructor() {
// 여기에 객체를 제거할 때 수행해야할 기능을 추가
}
}

class testext extends test {
// 생성자
function testext() {
$this->test();
// 여기에 객체를 생성할 때 수행해야할 기능을 추가
}

// 사용자 정의 소멸자
function testext_destructor() {
// 여기에 객체를 제거할 때 수행해야할 기능을 추가
$this->test_destructor();
}
}

$obj = new testext;
register_shutdown_function("__register_destructor");
.
.
.

?> [/code]
클래스가 상속관계에 있을 때에 각 클래스에 있는 소멸자의 실행순서는 파생클래스의 소멸자가 먼저 실행된 다음에 부모클래스의 소멸자가 순서대로 실행된다는 사실에 주의하세요. 따라서 아래와 같이 현재 클래스의 소멸자에서 처리할 내용을 먼저 수행한 후에 부모클래스의 소멸자를 수행하도록 작성하여야 합니다.
[code php;gutter:false] function testext_destructor() {
// 여기에 객체를 제거할 때 수행해야할 기능을 추가
$this->test_destructor();
} [/code]
PHP4에서의 소멸자
PHP3와 마찬가지로 소멸자를 지원하지 않습니다.

Posted by 방글24
phpclass/클래스활용2000. 6. 12. 14:52
생성자란?
생성자(constructor)는 객체가 만들어질 때 자동으로 호출되며 객체를 초기화시키는 것이 주임무입니다. 객체를 초기화한다는 것은 주로 데이터멤버 초기화, 메모리 할당 등을 수행한다는 것을 의미하지요. 이런 일 외에도 프로그래머 필요에 따라 생성자를 실행하는 중에 멤버 함수 또는 외부함수를 호출하여 프로그램을 시작하기 전에 필요한 기능을 수행할 수도 있습니다. 예를 들면 데이터베이스 연동에 필요한 초기작업과 같은 것이 있고, 데이터베이스와 연동되는 세션기능을 하는 클래스가 있다면 앞 페이지에서 데이터베이스에 저장된 데이터를 데이터베이스에서 읽어온 후 데이터멤버를 초기화하는 기능도 할 수 있겠지요. 또한 쿠키 설정을 생성자에서 수행하는 것이 편리할 수도 있습니다. 이와 같이 프로그래머의 아이디어에 따라서는 더 다양한 활용이 가능하리라 봅니다.
PHP3에서의 생성자
PHP3 에서 구현된 생성자는 그 기능이 매우 제한적으로 이루어지고 있습니다. 여러 개의 클래스가 상속관계에 있을 때, 프로그래머가 마지막으로 정의한 생성자만 수행할 수 있으며, 다른 생성자는 수행되지 않습니다. 이는 스크립트 내에 생성자를 위한 공간이 하나만 확보되어 있기 때문입니다.
이런 이유로 PHP 홈페이지의 온라인 매뉴얼에도 생성자를 사용할 때는 아래와 같이 주의하여 사용하도록 하고 있습니다. 아래는 Manual: Chapter 13. Classes and Objects 문서 중 마지막 부분 발췌한 내용입니다.
......
Caution For derived classes, the constructor of the parent class is not automatically called when the derived class's constructor is called.
......
따라서 프로그래머가 각 클래스마다 생성자를 정의하더라도 생성자로는 상속되지 않으며, 단지 일반 멤버함수로 상속됩니다. 생성자라는 것이 본래 목적이 객체가 만들어질 때 자동으로 호출되며 객체를 초기화시키는 것이 주임무로 최상위 클래스(top class)의 생성자로부터 최하위 파생클래스의 생성자까지 순서대로 호출되어야 하는 특별한 멤버함수입니다. 따라서 생성자로 상속된다면 이러한 생성자로서의 기능을 다해야 함에도 불구하고 PHP3에서 객체 생성할 때 마지막으로 정의된 클래스의 생성자만을 호출하고 그 이상의 부모클래스의 생성자는 실행하지 않고 종료합니다.
[code php;gutter:false] <?php

class test {
//
// 부모클래스의 생성자
//
function test() {
echo("class test:test() 부모클래스 생성자\n");
}
}

class test2 extends test {
//
// 파생클래스의 생성자
//
function test2() {
echo("class test2:test2() 파생클래스 생성자\n");
}
}

$obj = new test2;

?> [/code]
위 예제의 실행결과는 아래와 같습니다.
class test2:test2() 파생클래스 생성자
즉, 객체 생성할 때 마지막으로 정의된 클래스의 생성자만을 호출하고 종료합니다.
PHP3에서의 생성자 체인 구현
위에서 살펴본 바와 같이 PHP에서는 마지막으로 정의된 생성자만 객체 생성할 때 호출되기 때문에 만약 부모클래스의 생성자를 연속적으로 실행하려면 파생클래스의 생성자 내부에서 부모클래스의 생성자를 호출하여야 합니다.
이것이 가능한 것은 생성자의 함수명이 각 클래스마다 다르기 때문에 부모클래스에 정의된 생성자는 나중에 정의된 파생클래스의 생성자에 의해 덮어 쓰이게 되는 것이 아니라 일반 멤버함수로 계속 존재하게 됩니다. 따라서 마지막으로 정의된 생성자로부터 부모클래스의 생성자를 멤버함수로 접근할 수 있습니다.
[code php;gutter:false] class Cart {
var $items; // Items in our shopping cart

function Cart () {
$this->add_item ("10", 1);
}
// Add $num articles of $artnr to the cart

function add_item ($artnr, $num) {
$this->items[$artnr] += $num;
}

// Take $num articles of $artnr out of the cart

function remove_item ($artnr, $num) {
if ($this->items[$artnr] > $num) {
$this->items[$artnr] -= $num;
return true;
} else {
return false;
}
}
}

class Auto_Cart extends Cart {
function Auto_Cart () {
$this->Cart ();
}
} [/code]
get_parent_class 함수를 이용하면 더 개선된 로직을 구성할 수 있습니다.
[code php;gutter:false] class Auto_Cart extends Cart {
function Auto_Cart () {
$parent = get_parent_class($this);
$this->$parent ();
}
} [/code]
이처럼 C++과 같은 다른 객체지향언어와 같이 최상위 클래스로부터 최하위 클래스까지 순차적으로 생성자를 수행하기 위해서는 모든 파생클래스 생성자 내부에서 부모클래스의 생성자를 호출해 주는 코드를 포함시켜주면 됩니다.
PHP4에서의 생성자
PHP4 에서도 PHP3와 같이 마지막으로 정의된 생성자만 실행된다는 점에서 같습니다. 그러나 마지막 정의되는 위치가 어디냐에 따라 실행결과가 전혀 달라질 수 있으니 주의하셔야 합니다. 이에 대한 자세한 내용을 "클래스사용법"의 "생성자" 부분을 참조바랍니다.

Posted by 방글24
phpclass/클래스활용2000. 6. 12. 14:51
함수 재정의란?
객체지향언어에서 말하는 함수 재정의(함수 오버라이딩;function overriding)는 부모클래스(base class)에서 정의되어 있는 멤버함수를 파생클래스(derived class)에서 자신에 맞는 멤버함수로 재정의 하여 부모클래스의 멤버함수를 무효화시키는 경우를 말합니다. 이를 위해서는 재정의 하고자 하는 부모클래스에 있는 함수의 함수명, 파라미터 수 및 데이터형을 동일하게 하여 파생클래스에 정의하면 됩니다.
PHP3에서의 함수 재정의
위에서 정의한 의미로 보면 PHP3에서는 함수 재정의라는 것이 특별히 정의되어 있지 않습니다. PHP3는 스크립트라는 특성 때문인지 모르겠으나 함수명만 같으면 파라미터 수 또는 데이터형에 관계없이 몇 개의 함수를 정의하던지 하나만 유효합니다. 같은 클래스 내에서는 아래쪽에 정의된 함수만 유효하며 두개 이상의 클래스가 상속 관계에 있을 때는 파생클래스에서 정의된 함수만 유효합니다. 즉 나중에 정의된 함수만 접근할 수 있습니다.
예를 들어보면,
첫째, 같은 클래스 내에 동일한 함수명으로 정의한 경우
[code php;gutter:false] <?php

class test {
//
// 멤버함수 a() case #1
//
function a() {
echo("class test:a() case #1\n");
}

//
// 멤버함수 a() case #2
//
function a($k) {
echo("class test:a($k) case #2\n");
}
}

$obj = new test;
$obj->a("파라미터");

?> [/code]
두 개의 멤버함수 a($k)와 a() 중 a($k)만 유효합니다. 즉 나중에 정의된 것만 호출할 수 있습니다. 따라서 객체를 생성할 때와 멤버함수를 호출할 때 위의 예와 같이 $obj->a("파라미터"); 라고 기술해야지 $obj->a();와 같이 기술하면 에러가 발생합니다. 위 예제의 실행결과는 아래와 같습니다.
class test:a(파라미터) case #2
위에서 정의한 것은 함수의 파라미터수가 다르기 때문에 C++과 같은 객체지향언어에서는 함수 오버로딩(overloading;중복정의)에 해당됩니다. 즉, a($k)와 a() 함수 둘 다 유효해야 하나, PHP에서는 마지막 정의 함수만 유효하게 됩니다. 마치 오버라이딩(재정의)된 것처럼...
둘째, 상속관계에 있는 부모와 파생클래스에 각각 동일한 함수명으로 정의한 경우
[code php;gutter:false] <?php

class test {
//
// 멤버함수 a() case #1
//
function a($k) {
echo("class test:a($k) case #1\n");
}
}

class test2 extends test {
//
// 멤버함수 a() case #2
//
function a($k) {
echo("class test2:a($k) case #2\n");
}
}

$obj = new test2;
$obj->a("파라미터");

?> [/code]
위 예제의 실행결과는 아래와 같습니다.
class test2:a(파라미터) case #2
즉, 동일한 이름으로 정의된 함수가 부모클래스와 파생클래스에 각각 정의하게 되면 나중에 나타나는 파생클래스에서 정의된 함수만 유효합니다.
PHP3에서의 함수 오버라이딩(재정의) 구현
PHP 에서는 파라미터 수 관계없이 함수명만 같으면 몇 개를 정의하더라도 마지막에 정의된 것만 유효하므로 특별히 함수 오버라이딩을 구현할 필요가 없습니다. 프로그래머가 알아서 파라미터 수를 같게 해서 정의하고 사용할 때 데이터형을 정확하게 맞춰주면 그것이 오버라이딩과 같은 효과를 얻을 수 있습니다. 문제는 오히려 함수 중복정의(오버로딩)가 안 된다는데 있습니다.
PHP4에서의 함수 재정의
PHP4에서는 재정의(?)되기 이전의 원래 메소드에 접근하기 위한 범위연산자가 제공되고 있습니다. 자세한 것은 "클래스사용법"의 범위연산자를 참조하세요.

Posted by 방글24