phpclass/클래스활용2000. 7. 13. 14:03
생성자(constructor)는 클래스의 새로운 인스턴스가 생성될 때 자동적으로 호출되는 클래스 내의 함수이며, 클래스명과 동일한 이름를 갖는 특수한 메소드입니다.
[code php;gutter:false] class Cart {
var $items; // Items in our shopping cart

// 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->add_item ("10", 1);
}
} [/code]
위의 예제는 클래스 Auto_Cart가 new 연산자로 만들어질 때마다 품목번호 "10"의 수량이 1을 갖도록 장바구니를 초기화시키는 생성자를 새로이 포함하여 정의하였습니다.
생성자에 전달되는 인자
생성자는 필요하면 선택적으로 인자(argument)를 전달할 수도 있기 때문에 매우 유용하게 사용됩니다.
[code php;gutter:false] class Constructor_Cart extends Cart {
function Constructor_Cart ($item = "10", $num = 1) {
$this->add_item ($item, $num);
}
}

// Shop the same old boring stuff.

$default_cart = new Constructor_Cart;

// Shop for real...

$different_cart = new Constructor_Cart ("20", 17); [/code]
PHP3와 PHP4 생성자 사이에 발생하는 미묘한 차이
PHP3에서는 클래스와 동일한 이름을 가진 함수를 생성자로 처리하고 있습니다. 따라서 아래와 같은 경우에 클래스 B의 이름과 동일한 이름의 함수 B()가 없으므로 객체를 생성할 때 실행할 생성자가 없습니다.
[code php;gutter:false] class A {
function A() {
echo "I am the constructor of A.\n";
}
}

class B extends A {
function C() {
echo "I am a regular function.\n";
}
}

// no constructor is being called in PHP3.
$b = new B; [/code]
그러나 만약 아래와 같이 클래스 A에 함수 B()가 정의되어 있다면 설사 클래스 B를 가지고 객체를 생성하더라도 클래스 A에 있는 일반함수 B()를 클래스 B의 생성자로 인식합니다. 즉, PHP3에서는 함수 B()가 클래스 B에 속해 있는지 아니면 부모 클래스로부터 상속된 함수인지를 인식하지 못합니다. 따라서 객체 $b를 생성할 때 클래스 A에 있는 일반함수 B()를 생성자로써 실행하게 되는 것이지요.
[code php;gutter:false] class A {
function A() {
echo "I am the constructor of A.\n";
}

function B() {
echo "I am a regular function named B in class A.\n";
echo "I am not a constructor in A.\n";
}
}

class B extends A {
function C() {
echo "I am a regular function.\n";
}
}

// no constructor is being called in PHP3.
$b = new B; [/code]
클래스 B에 속하지도 않은, 부모클래스로부터 상속된 일반 함수 B()를 클래스 B의 생성자로 인식한다는 것은 대부분 우리가 전혀 의도하지 않는 일로 잘못하다가는 원치않는 결과를 초래할 수도 있습니다. 객체지향언어에서 말하는 생성자의 구분이 모호해 진다는 것이지요. 이러한 문제를 PHP4에서는 바로 잡았습니다. 단지 이름만 같다고 생성자로 처리하는 것이 아니라 반드시 해당 클래스 내에 포함되어 있는 것만 생성자로 처리하도록 수정하였습니다. 따라서 위의 예를 PHP4에서 수행한다면 클래스 A에 속한 일반함수 B()를 생성자로써 실행하지는 않습니다.
대신에 PHP4에서는 생성자와 관련하여 새로운 기능이 추가되었습니다. 파생클래스에서 생성자가 정의되어 있지 않으면 그 부모 클래스에 정의된 생성자가 실행하도록 수정되었습니다. 즉, 위의 예에서보면 객체 $b를 생성할 때 클래스 B에 해당하는 생성자 B() 함수가 정의되어 있지 않으므로 그 부모 클래스의 생성자인 A()가 생성자로 수행됩니다.
이러한 PHP3와 PHP4 사이의 미묘한 차이를 명확히 구분하지 못한 상태에서 생성자를 다루게 되면 프로그램이 매우 심각한 오류에 빠질 수 있다는 것을 참고하시기 바랍니다.

Posted by 방글24
phpclass/클래스활용2000. 7. 13. 14:02
클래스를 상속하려면?
기존에 이미 작성된 클래스를 상속(class inheritance)받으면 이미 작성된 메소드와 멤버변수를 그대로 이어받게 됩니다. 상속받은 특성에 덧붙여 새로운 특성을 추가하는 방법으로 새로운 클래스를 정의하게 됩니다. 이와 같이 기존의 클래스로부터 특성을 이어받는 것을 상속이라고 합니다. 이 때 확장된 클래스를 정의하기 위해 "extends"라는 키워드를 사용합니다.
부모클래스 & 자식클래스에 관련된 용어
기존의 클래스와 확장된 클래스를 나타내는 용어는 객체지향언어마다 다양하게 사용되고 있습니다. 그러나 어떤 용어를 사용하더라도 같은 의미로 사용되고 있다고 이해하시면 됩니다.
기존의 클래스 확장된 클래스
용어 영문 용어 영문
기반클래스 base class 파생클래스 derived class
수퍼클래스 super class 서브클래스 sub class
부모클래스 parent class 자식클래스 child class
클래스 상속 예제
[code php;gutter:false] class Cart {
var $items; // Items in our shopping cart

// 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 Named_Cart extends Cart {
var $owner;

function set_owner ($name) {
$this->owner = $name;
}
} [/code]
클래스 Named_Cart는 클래스 Cart의 모든 변수와 함수를 그대로 상속받게 되며, 새로운 멤버인 변수 $owner과 함수 set_owner()를 추가하여 정의합니다. 앞서 배운 new 연산자를 이용하여 클래스 Named_Cart의 객체를 생성한 후 장바구니 주인을 지정하거나 주인이 누구인지 확인할 수 있습니다. 아울러 부모클래스 Cart에 있는 장바구니 관련 함수를 그대로 사용할 수 있습니다.
[code php;gutter:false] $ncart = new Named_Cart; // Create a named cart
$ncart->set_owner ("kris"); // Name that cart
print $ncart->owner; // print the cart owners name
$ncart->add_item ("10", 1); // (inherited functionality from cart) [/code]
단일 상속
PHP는 다중 상속(multiple inheritance)를 지원하지 않으며, 오로지 단일 상속만 지원합니다.

Posted by 방글24
phpclass/클래스활용2000. 7. 13. 14:00
객체 생성=객체 초기화(object initialization)=인스턴스화(instantiation)
클래스는 붕어빵을 만드는 틀(= type, =template)과 같은 것으로, 클래스 내에 정의된 메소드와 멤버변수를 사용하기 위해서는 틀을 가지고 붕어빵을 만드는 것같이 객체를 생성하여야 합니다. 객체(object)를 초기화하는 방법은 new 연산자를 사용하여 객체를 변수에 인스턴스 시키는 것입니다.
[code php;gutter:false] class Cart {
var $items; // Items in our shopping cart

// 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;
}
}
}

$cart = new Cart;
$cart->add_item("10", 1); [/code]
위와 같이 하면 클래스 Cart에 대한 객체 $cart가 생성됩니다. 객체 함수 add_item()은 장바구니에 품목번호 "10"의 수량을 1개 추가하기 위해 호출됩니다.
지정연산자 "->"의 의미
"->" 는 객체의 멤버변수 또는 메소드를 지정하는데 사용되는 지정연산자입니다. C++ 언어를 접해 본 분은 쉽게 이해하시겠지만, new 연산자로 생성되는 객체를 나타내는 객체명에는 실제로 객체의 멤버(변수 또는 함수)가 존재하는 것이 아니라 객체의 멤버가 존재하는 메모리상에 위치를 나타내는 주소(adress)가 담겨져 있습니다. 이와 같이 객체지향언어에서는 주소를 가지고 멤버를 참조하려면 아래와 같이 지정연산자 "->"를 이용하게 됩니다.
멤버변수를 참조할 때 : 객체명->변수;
메소드를 참조할 때 : 객체명->함수;
C++ 언어에서는 "->"를 화살표 멤버 연산자라고 말하며, "->"의 앞쪽에 있는 식별자(여기서는 객체명)가 포인터(pointer; 주소를 의미함)일 때 그 멤버를 참조하기 위한 연산자입니다.
지역 변수에 초기화된 객체
객체를 지역변수에 인스턴스할 수 있기 때문에, 클래스를 정의하고 객체를 생성하는 것을 하나의 모듈로 개발할 수 있습니다.
[code php;gutter:false] <?php

function class_in_function() {
class test {
var $a = 10;
function test() {
echo "함수 내에 정의된 클래스의 생성자 실행\n";
}
function echo_test() {
echo "함수 내에 정의된 클래스의 멤버변수 \$a의 값 = ".$this->a."\n";
}
}

$obj = new test;
$obj->echo_test();
}

class_in_function();
?> [/code]
< 예제 코드 >
함수 내에 정의된 클래스의 생성자 실행
함수 내에 정의된 클래스의 멤버변수 $a의 값 = 10
< 실행 결과 >
객체 생성할 때 생성자명을 가변함수로 지정하기
[code php;gutter:false] $classname = "MiniDB";
$obj = new $classname(); [/code]
이 코드는 PHP3와 PHP4 모두에서 정상적으로 동작합니다.
메소드명을 변경하기(가변함수)
PHP의 매뉴얼을 보면 가변함수(variable function)를 지원하는데 이것은 변수명 뒤에 괄호가 왔을 때, PHP는 그 이름을 가진 함수를 찾아 실행하는 것입니다. 이것은 클래스의 메소드에서도 그대로 사용할 수 있습니다.
[code php;gutter:false] class test {
function A() {
echo "나 A 함수\n";
}
}

$obj = new test;

$method = "A";
$obj->$method(); [/code]
이것을 응용하여 같은 실행문으로 A0, A1, A2라는 메소드에 번갈아 가면서 접근하려면 역시 가변함수를 사용하면 됩니다.
[code php;gutter:false] class test {
function A0() {
echo "나 A0 함수\n";
}

function A1() {
echo "나 A1 함수\n";
}
function A2() {
echo "나 A2 함수\n";
}
}

$obj = new test;

for ($i=0;$i<3;$i++) {
$method = "A$i" ;
$obj->$method();
} [/code]
위에 것은 모두 PHP3와 PHP4에서 모두 동작되는 코드입니다. 만약, PHP4에서만 동작시켜도 무방하다면 아래와 같이 중괄호를 이용하면 소스를 간결하게 코딩할 수 있습니다.
[code php;gutter:false] for ($i=0;$i<3;$i++) {
$obj->{"a$i"}();
} [/code]
객체명을 변경하기(가변변수)
가변변수(Variable Variables)의 유용함은 모두 알고 있겠지만 PHP4에서는 별문제가 없지만 PHP3에서 객체변수를 가변변수로 사용하기는 그리 쉽지 않습니다.
[code php;gutter:false] class test {
var $hello = "hello world";
}

$obj = new test;
$a = "obj";
echo $$a->hello; // or echo ${$a}->hello; [/code]
PHP3에서 위와 같이 작성하여 실행한다면,
Object
Parse error: parse error, ...... test.php3 on line 9
위와 같은 에러를 만나게 됩니다. 그러나 PHP4에서는 객체변수에도 가변변수를 제대로 지원하기 시작했습니다. 따라서 위의 예제가 에러없이 잘 실행되지요. 그러면 PHP3에서는 객체변수의 이름을 변경할 수 없을까요? 아래와 같이 $GLOBALS 배열을 사용해 보세요. 아무 문제없이 잘 실행될 겁니다.
[code php;gutter:false] class test {
var $hello = "hello world";
}

$obj = new test;
$a = "obj";
echo $GLOBALS[$a]->world(); [/code]
따라서 PHP3와 PHP4 모두에서 동작되기를 바란다면 $GLOBALS 배열을 이용하여 작성하세요.
배열구조의 멤버변수를 가변변수로 다루는 방법
[code php;gutter:false] class test {
var $arr = array();

function test() {
$this->arr[0] = 0;
$this->arr[1] = 1;
}
}

$obj = new test; [/code]
위와 같이 클래스 test에 배열 구조의 멤버변수가 있을 때, 이러한 멤버변수의 배열 요소에 접근하려면 $obj->arr[0]; 와 같이 사용하면 됩니다. 여기서 멤버변수명 "arr"을 가변변수로 처리하려면,
[code php;gutter:false] $prop = "arr";
$obj->{"$prop"}[0]; [/code]
위와 같이 가변변수 $prop를 중괄호로 묶어주세요. 여기서 겹따옴표는 생략해도 됩니다. PHP3와 PHP4에서 모두 잘 동작할 것입니다.

Posted by 방글24