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
phpclass/클래스활용2000. 6. 12. 14:49
여기서는 객체지향언어에 대한 이론을 설명하지는 않을 것이며, 단지 객체지향언어에서 다루어지는 기본 개념을 중심으로 PHP에서 어떻게 표현되는가를 다룰 것입니다. 객체지향언어 이론에 대하여 궁금하면 관련서적, 웹사이트를 방문해 보세요.
함수 중복정의(함수 오버로딩;function overloading)란?
함수 오버로딩이란 같은 이름을 가지고 파라미터의 리스트만 다른 함수 여러 개를 생성하는 방법입니다. 이것의 목적은 데이터의 데이터형만 다르다면, 같은 함수 이름으로도 각각의 데이터 데이터형에 맞게 알맞은 연산을 수행하도록 하는 데 있습니다.
PHP3에서의 함수 오버로딩
PHP3 에서는 이와 같이 함수를 중복 정의할 수 있는 함수 오버로딩을 지원하지 않습니다. 이것은 PHP 홈페이지에 게시된 공식문서에서도 잘 나타나 있습니다. 아래는 http://www.php.net/manual/utiltions.php3 문서 내용 중에서 발췌한 것입니다. 이 문서는 오래된 문서라 현재 온라인 상으로는 확인되지 않습니다.
......
PHP does not support function overloading,
nor is it possible to undefine or redefine previously-declared functions.
......
PHP3에서의 함수 오버로딩 구현
PHP 에서 지원하는 변수에 대한 데이터형에는 "integer(정수형)", "double(실수형)", "string(문자열)", "array(배열)", "object(객체)"가 있습니다. 그러나 PHP에서는 C에서처럼 변수에 대한 데이터형을 미리 선언할 필요가 없습니다. 그런데 함수 오버로딩에서는 인수의 데이터형을 가지고 같은 이름의 여러 개의 함수들을 구분시켜 줍니다. 따라서 PHP에서도 함수 오버로딩을 구현하려면 데이터형을 지정할 필요가 있으며 인수의 데이터형이 맞는 함수가 없을 때는 함수명이 같더라도 아무것도 실행해서는 안됩니다. PHP에서는 함수의 인수에 데이터형을 지정할 수 없지만 지정할 수 있다고 가정하고 아래와 같은 함수 오버로딩을 구현할 방법을 찾아보도록 하겠습니다.
[code php;gutter:false] class test {
var $int_value; // 정수형이 저장될 데이터멤버
var $str_value; // 문자열이 저장될 데이터멤버

function setvalue(integer $int_val) {
$this->int_value = $int_val;
}

function setvalue(string $str_val) {
$this->str_value = $str_val;
}

function setvalue(string $str_val, integer $int_val) {
$this->int_value = $int_val;
$this->str_value = $str_val;
}
} [/code]
위와 같은 함수 오버로딩을 구현하려면 아래와 같이 오버로딩 함수명에서 각 인수의 데이터형을 판단하여 데이터형에 맞는 해당 함수로 분기시켜주면 됩니다.
[code php;gutter:false] class test {
var $int_value; // 정수형이 저장될 데이터멤버
var $str_value; // 문자열이 저장될 데이터멤버

function setvalue ($p0="_", $p1="_") {
if (gettype($p0) == "string" && $p0 != "_"
&& gettype($p1) == "integer") {
return $this->setvalue2($p0, $p1);
} else if (gettype($p0) == "string" && $p0 != "_") {
return $this->setvalue1($p0);
} else if (gettype($p0) == "integer") {
return $this->setvalue0();
} else {
die("에러발생");
}
}

function setvalue0 ($int_val) {
$this->int_value = $int_val;
}

function setvalue1 ($str_val) {
$this->str_value = $str_val;
}

function setvalue2 ($str_val, $int_val) {
$this->int_value = $int_val;
$this->str_value = $str_val;
}
} [/code]
PHP4에서의 함수 오버로딩
2000 년5월22일 작성된 온라인 매뉴얼을 살펴보면 PHP4에서도 아직 함수 오버로딩을 지원하지 않는 것 같습니다. 아래는 Chapter 12. Functions User-defined functions 문서 내용 중에서 발췌한 것입니다.
......
In PHP3, functions must be defined before they are referenced.
No such requirement exists in PHP4.

PHP does not support function overloading, nor is it possible to undefine or
redefine previously-declared functions.

PHP3 does not support variable numbers of arguments to functions,
although default arguments are supported
(see Default argument values for more information).
PHP4 supports both: see Variable-length argument lists and
the function references for func_num_args(),
func_get_arg(), and func_get_args() for more information.
http://www.php.net/manual/utiltions.php 05/22/00
......
혹시 함수 오버로딩을 사용할 경우가 생긴다면(별로 없겠지만) PHP에서 정식으로 지원할 때까지는 불편하더라도 PHP3용으로 구현된 함수 오버로딩 코드를 PHP4에서도 계속 사용해야 할 것 같습니다.

Posted by 방글24