shop-wiz logo
PHP 클라스 설명
1. 클라스 정의


클래스란?

클래스는 객체의 변수와 함수를 정의하는 템플릿이며, 이에 따라 변수로 표현되는 데이터 영역과 이러한 데이터 영역에 접근할 수 있는 함수로 구성됩니다. 클래스 내에 정의된 변수를 멤버변수(member variable)라고 하고 함수를 메쏘드(method)라고 합니다. C++과 같은 객체지향언어에서는 멤버변수를 데이터멤버, 메쏘드를 멤버함수라고 호칭합니다. PHP에서 클래스를 사용하는 것은 C++ 또는 자바와 거의 비슷합니다.

클래스 정의

클래스를 정의(class definition)할 때는 키워드 "class"를 사용합니다. 클래스를 구성하는 멤버변수와 메쏘드를 정의할 때는 "var"과 "function"이라는 키워드를 사용합니다. "function"은 일반 함수를 정의할 때도 사용되지만 "var"은 클래스의 멤버변수를 정의할 때만 사용되는 키워드로, 멤버변수를 정의할 때는 반드시 명시하여야 합니다. 예를 들어 클래스는 아래와 같이 정의합니다. 이 예는 PHP 매뉴얼에 있는 것으로 수정하지 않고 가져왔습니다. 이 예에서는 $items라는 멤버변수와 add_item, remove_item라는 메쏘드가 정의되어 있습니다.

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

멤버변수의 초기화

PHP에서는 멤버변수값을 아래와 같이 상수 또는 변수를 이용하여 초기화할 수 있습니다.

상수로 초기화할 때 :

class Cart {
  var $items = 0;  // Items in our shopping cart
}

변수로 초기화할 때(1) :

class Cart {
  var $items;  // Items in our shopping cart

  function Cart($items) {
    $this->items = $items;
  }
}

변수로 초기화할 때(2) :

$items = 0;

class Cart {
  var $items = $GLOBALS["items"];  // Items in our shopping cart
}

반면 PHP4에서는 var 변수에는 상수로만 초기화할 수 있고, 상수가 아닌 값을 가지고 초기화할 때는 생성자를 이용하여야 합니다. 즉, var $items = $GLOBALS["items"];와 같은 표현은 허용하지 않습니다.

따라서 아래와 같은 표현은 PHP4에서는 허용하지 않습니다.

class Cart {
  var $todays_date = date("Y-m-d");
  var $name = $firstname;
  var $owner = 'Fred ' . 'Jones';
  var $items = array("VCR", "TV");
}

PHP4에서 초기화할 때 동일한 결과를 얻으려면 아래와 같이 생성자를 이용합니다.

class Cart {
  var $todays_date;
  var $name;
  var $owner;
  var $items;

  function Cart() {
    $this->todays_date = date("Y-m-d");
    $this->name = $GLOBALS['firstname'];
    /* etc. . . */
  }
}

PHP4 예약어

stdClass

stdClass는 Zend에서 내부적으로 사용하고 있는 예약어입니다. 따라서 사용자는 클래스명으로 stdClass를 사용할 수 없습니다. get_declared_classes() 함수를 사용하면 현재 스크립트에 정의된 클래스명을 배열에 담아 되돌려 줍니다. 따라서 이 함수를 이용하면 stdClass의 존재를 확인할 수 있습니다.

<?php

class Vegetable {

}

class Spinach extends Vegetable {

}

$arr_class = get_declared_classes();

while (list($k,$v)=each($arr_class)) {
  echo("\$arr_class[$k]=$v");
}

?>

이 문서를 실행하면 아래와 같은 결과를 얻을 수 있습니다.

$arr_class[0]=stdClass
$arr_class[1]=OverloadedTestClass
$arr_class[2]=Directory
$arr_class[3]=OCI-Lob
$arr_class[4]=vegetable
$arr_class[5]=spinach

위 예제의 실행결과를 보면, 사용자가 정의한 vegetable, spinach 외에도 stdClass, OverloadedTestClass, Directory, OCI-Lob가 있는 것을 볼 수 있습니다. 좀 더 자세한 것은 메뉴 "클래스&객체 함수 >> get_declared_classes()"를 살펴보시기 바랍니다.

매직함수(magic function)

__sleep, __wakeup과 같이 "__"로 시작하는 매직함수는 PHP 클래스 내에서 특수한 목적으로 사용됩니다. 따라서 이 함수들이 가지고 있는 문서화된 매직 기능을 사용할 필요가 없다면 클래스 내에 이 함수들을 정의해서는 안됩니다. 자세한 것은 메뉴에서 "매직함수"장을 살펴보기 바랍니다.

$this가 무엇에 쓰는 물건인고?

클래스 메쏘드 내에서만 사용되며, 클래스의 현재 인스턴스를 참조할 때 사용하는 변수이며, 예를 들어 현재 객체 내에 something라고 명명된 임의의 변수 또는 함수를 참조하기 위해서는 $this->something을 사용하여야 합니다. 즉, "$this"의 의미는 new 연산자에 의해 생성될 객체 자신을 의미합니다. 그러니 아직 생성되지 않은 객체 자신을 의미하는 의사(擬似)변수(pseudo variable)이며, "my own" 또는 "current object"라고 불리웁니다.

앞에서 클래스를 붕어빵 틀과 같다고 했습니다. 정의된 클래스에 의해 생성된 객체는 붕어빵 틀로 만들어낸 수많은 붕어빵이지요. 아래 예에서 본다면, $붕어빵1->make("특급밀가루")으로 make() 메쏘드에 접근한다면 이 때 make() 메쏘드 내의 $this는 $붕어빵1을 의미하고, $붕어빵2->make("중급밀가루")으로 접근한다면 이 때 $this는 $붕어빵2를 의미하고, $붕어빵3->make("저급밀가루")으로 접근한다면 이 때 $this는 $붕어빵3을 의미합니다.

class 붕어빵 {
  var 재료;

  function make($재료) {
    $this->재료 = $재료;
    ......
  }
}

$붕어빵1 = new 붕어빵; // 인스턴스 "붕어빵1"
$붕어빵2 = new 붕어빵; // 인스턴스 "붕어빵2"
$붕어빵3 = new 붕어빵; // 인스턴스 "붕어빵3"

$붕어빵1->make("특급밀가루");
$붕어빵2->make("중급밀가루");
$붕어빵3->make("저급밀가루");
2. 객체 생성


객체 생성=객체 초기화(object initialization)=인스턴스화(instantiation)

클래스는 붕어빵을 만드는 틀(= type, =template)과 같은 것으로, 클래스 내에 정의된 메쏘드와 멤버변수를 사용하기 위해서는 틀을 가지고 붕어빵을 만드는 것같이 객체를 생성하여야 합니다. 객체(object)를 초기화하는 방법은 new 연산자를 사용하여 객체를 변수에 인스턴스 시키는 것입니다.

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);

위와 같이 하면 클래스 Cart에 대한 객체 $cart가 생성됩니다. 객체 함수 add_item()은 장바구니에 품목번호 "10"의 수량을 1개 추가하기 위해 호출됩니다.

지정연산자 "->"의 의미

"->"는 객체의 멤버변수 또는 메쏘드를 지정하는데 사용되는 지정연산자입니다. new 연산자로 생성되는 객체를 나타내는 객체명에는 실제로 객체의 멤버(변수 또는 함수)가 존재하는 것이 아니라 객체의 멤버가 존재하는 메모리상에 위치를 나타내는 주소(adress)가 담겨져 있습니다. 이와 같이 객체지향언어에서는 주소를 가지고 멤버를 참조하려면 아래와 같이 지정연산자 "->"를 이용하게 됩니다.

멤버변수를 참조할 때 : 객체명->변수;
메쏘드를 참조할 때 : 객체명->함수;

"->"를 화살표 멤버 연산자라고 말하며, "->"의 앞쪽에 있는 식별자(여기서는 객체명)가 포인터(pointer; 주소를 의미함)일 때 그 멤버를 참조하기 위한 연산자입니다.

지역 변수에 초기화된 객체

객체를 지역변수에 인스턴스할 수 있기 때문에, 클래스를 정의하고 객체를 생성하는 것을 하나의 모듈로 개발할 수 있습니다.

예제 코드 :

<?php

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

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

class_in_function();
?> 

실행 결과 :

함수 내에 정의된 클래스의 생성자 실행
함수 내에 정의된 클래스의 멤버변수 $a의 값 = 10

객체 생성할 때 생성자명을 가변함수로 지정하기

$classname = "MiniDB";
$obj = new $classname();

이 코드는 PHP와 PHP4 모두에서 정상적으로 동작합니다.

메쏘드명을 변경하기(가변함수)

PHP의 매뉴얼을 보면 가변함수(variable function)를 지원하는데 이것은 변수명 뒤에 괄호가 왔을 때, PHP는 그 이름을 가진 함수를 찾아 실행하는 것입니다. 이것은 클래스의 메쏘드에서도 그대로 사용할 수 있습니다.

class test { 
  function A() { 
    echo "나 A 함수<BR> \n"; 
  } 
} 

$obj = new test; 

$method = "A"; 
$obj->$method();

이것을 응용하여 같은 실행문으로 A0, A1, A2라는 메쏘드에 번갈아 가면서 접근하려면 역시 가변함수를 사용하면 됩니다.

class test { 
  function A0() { 
    echo "나 A0 함수<BR> \n"; 
  } 

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

$obj = new test; 

for ($i=0;$i<3;$i++) { 
    $method = "A$i" ; 
    $obj->$method(); 
}

위에 것은 모두 PHP3와 PHP4에서 모두 동작되는 코드입니다. 만약, PHP4에서만 동작시켜도 무방하다면 아래와 같이 중괄호를 이용하면 소스를 간결하게 코딩할 수 있습니다.

for ($i=0;$i<3;$i++) { 
  $obj->{"a$i"}(); 
}

객체명을 변경하기(가변변수)

가변변수(Variable Variables)의 유용함은 모두 알고 있겠지만 PHP4에서는 별문제가 없지만 PHP에서 객체변수를 가변변수로 사용하기는 그리 쉽지 않습니다.

class test { 
  var $hello = "hello world";
} 

$obj = new test; 
$a = "obj"; 
echo $$a->hello; // or echo ${$a}->hello;

PHP에서 위와 같이 작성하여 실행한다면,

Object Parse error: parse error, ...... test.php3 on line 9

와 같은 에러를 만나게 됩니다. 그러나 PHP4에서는 객체변수에도 가변변수를 제대로 지원하기 시작했습니다. 따라서 위의 예제가 에러없이 잘 실행되지요. 그러면 PHP에서는 객체변수의 이름을 변경할 수 없을까요? 아래와 같이 $GLOBALS 배열을 사용해 보세요. 아무 문제없이 잘 실행될 겁니다.

class test { 
  var $hello = "hello world"; 
} 

$obj = new test; 
$a = "obj"; 
echo $GLOBALS[$a]->world();

따라서 PHP3와 PHP4 모두에서 동작되기를 바란다면 $GLOBALS 배열을 이용하여 작성하세요.

배열구조의 멤버변수를 가변변수로 다루는 방법

class test { 
  var $arr = array(); 

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

$obj = new test;

위와 같이 클래스 test에 배열 구조의 멤버변수가 있을 때, 이러한 멤버변수의 배열 요소에 접근하려면 $obj->arr[0]; 와 같이 사용하면 됩니다. 여기서 멤버변수명 "arr"을 가변변수로 처리하려면,

$prop = "arr"; 
$obj->{"$prop"}[0];

와 같이 가변변수 $prop를 중괄호로 묶어주세요. 여기서 겹따옴표는 생략해도 됩니다. PHP3와 PHP4에서 모두 잘 동작할 것입니다.

3. 클래스 상속


클래스를 상속하려면?

기존에 이미 작성된 클래스를 상속(class inheritance)받으면 이미 작성된 메쏘드와 멤버변수를 그대로 이어받게 됩니다. 상속받은 특성에 덧붙여 새로운 특성을 추가하는 방법으로 새로운 클래스를 정의하게 됩니다. 이와 같이 기존의 클래스로부터 특성을 이어받는 것을 상속이라고 합니다. 이 때 확장된 클래스를 정의하기 위해 "extends"라는 키워드를 사용합니다.

부모클래스 & 자식클래스에 관련된 용어

기존의 클래스와 확장된 클래스를 나타내는 용어는 객체지향언어마다 다양하게 사용되고 있습니다. 그러나 어떤 용어를 사용하더라도 같은 의미로 사용되고 있다고 이해하시면 됩니다.

기존의 클래스 확장된 클래스
용어 영문 용어 영문
기반클래스 base class 파생클래스 derived class
수퍼클래스 super class 서브클래스 sub class
부모클래스 parent class 자식클래스 child class

클래스 상속 예제

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

클래스 Named_Cart는 클래스 Cart의 모든 변수와 함수를 그대로 상속받게 되며, 새로운 멤버인 변수 $owner과 함수 set_owner()를 추가하여 정의합니다. 앞서 배운 new 연산자를 이용하여 클래스 Named_Cart의 객체를 생성한 후 장바구니 주인을 지정하거나 주인이 누구인지 확인할 수 있습니다. 아울러 부모클래스 Cart에 있는 장바구니 관련 함수를 그대로 사용할 수 있습니다.

$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)

단일 상속

PHP는 다중 상속(multiple inheritance)를 지원하지 않으며, 오로지 단일 상속만 지원합니다.

4. 생성자


생성자란?

생성자(constructor)는 클래스의 새로운 인스턴스가 생성될 때 자동적으로 호출되는 클래스 내의 함수이며, 클래스명과 동일한 이름를 갖는 특수한 메쏘드입니다.

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

위의 예제는 클래스 Auto_Cart가 new 연산자로 만들어질 때마다 품목번호 "10"의 수량이 1을 갖도록 장바구니를 초기화시키는 생성자를 새로이 포함하여 정의하였습니다.

생성자에 전달되는 인자

생성자는 필요하면 선택적으로 인자(argument)를 전달할 수도 있기 때문에 매우 유용하게 사용됩니다.

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);

PHP5 이상에서는 아래와 같이 생성자(construct)를 정의하실 수 잇습니다.
class Constructor_Cart extends Cart {
	function __construct ($item = "10", $num = 1) {
		//실행화일
	}
}

PHP3와 PHP4 생성자 사이에 발생하는 미묘한 차이

PHP에서는 클래스와 동일한 이름을 가진 함수를 생성자로 처리하고 있습니다. 따라서 아래와 같은 경우에 클래스 B의 이름과 동일한 이름의 함수 B()가 없으므로 객체를 생성할 때 실행할 생성자가 없습니다.


class A {
  function A() {
    echo "I am the constructor of A.<br>\n";
  }
}

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

// no constructor is being called in PHP.
$b = new B;

그러나 만약 아래와 같이 클래스 A에 함수 B()가 정의되어 있다면 설사 클래스 B를 가지고 객체를 생성하더라도 클래스 A에 있는 일반함수 B()를 클래스 B의 생성자로 인식합니다. 즉, PHP에서는 함수 B()가 클래스 B에 속해 있는지 아니면 부모 클래스로부터 상속된 함수인지를 인식하지 못합니다. 따라서 객체 $b를 생성할 때 클래스 A에 있는 일반함수 B()를 생성자로써 실행하게 되는 것이지요.

class A {
  function A() {
    echo "I am the constructor of A.<br>\n";
  }

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

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

// no constructor is being called in PHP.
$b = new B;

클래스 B에 속하지도 않은, 부모클래스로부터 상속된 일반 함수 B()를 클래스 B의 생성자로 인식한다는 것은 대부분 우리가 전혀 의도하지 않는 일로 잘못하다가는 원치않는 결과를 초래할 수도 있습니다. 객체지향언어에서 말하는 생성자의 구분이 모호해 진다는 것이지요. 이러한 문제를 PHP4에서는 바로 잡았습니다. 단지 이름만 같다고 생성자로 처리하는 것이 아니라 반드시 해당 클래스 내에 포함되어 있는 것만 생성자로 처리하도록 수정하였습니다. 따라서 위의 예를 PHP4에서 수행한다면 클래스 A에 속한 일반함수 B()를 생성자로써 실행하지는 않습니다.

대신에 PHP4에서는 생성자와 관련하여 새로운 기능이 추가되었습니다. 파생클래스에서 생성자가 정의되어 있지 않으면 그 부모 클래스에 정의된 생성자가 실행하도록 수정되었습니다. 즉, 위의 예에서보면 객체 $b를 생성할 때 클래스 B에 해당하는 생성자 B() 함수가 정의되어 있지 않으므로 그 부모 클래스의 생성자인 A()가 생성자로 수행됩니다.

이러한 PHP3와 PHP4 사이의 미묘한 차이를 명확히 구분하지 못한 상태에서 생성자를 다루게 되면 프로그램이 매우 심각한 오류에 빠질 수 있다는 것을 참고하시기 바랍니다.

***** 주의 *****

PHP4에서의 개선내용은 http://www.php.net/manual/en/language.oop.constructor.php에서 문서화된 내용입니다만 실제로 PHP4는 이 문서와 같이 동작하지 않는 것으로 보고되고 있습니다(아래 주소 참조할 것).

http://www.phpbuilder.com/lists/php-documentation-list/2003031/0100.php

이러한 문제로 인하여 2003년 2월 17일 bugs.php.net에 공식적으로 버그리포팅되어 있습니다.

http://bugs.php.net/bug.php?id=22253

2003년 2월 17일 당시에는 PHP 버전 4.3.1이 공개된 시점으로 이 이후 버전에서도 이 버그는 개선되지 않고 있습니다. 위에서 언급한 www.phpbuilder.com에 의하면 PHP3와 php4가 동일하게 동작하며, 단지 PHP5에서만 개선된 내용대로 동작하고 있음을 알 수 있습니다.

5. 범위연산자


범위연산자란?

PHP4에서만 지원되며 클래스와 메쏘드 또는 클래스와 멤버변수를 연결시켜 주는 일로 범위연산자(scope resolver) 뒤에 나오는 메쏘드와 멤버변수의 스코프(사용범위)를 지정하는 일을 하는 것입니다.

클래스명::메쏘드명
클래스명::멤버변수명

범위연산자 사용목적

1. 인스턴스되지 않은 클래스의 메쏘드에 접근할 때
2. 부모클래스의 메쏘드와 멤버변수에 접근할 때

인스턴스되지 않은 클래스에 있는 메쏘드에 접근할 때

class A {
  function example() {
    echo "클래스 A에 정의된 메쏘드 example. <br>\n";
  }
}

A::example();

아직 클래스 A에 대한 객체가 생성되기 전이지만 범위연산자를 이용하면 일반 함수처럼 실행시킬 수 있습니다. 그러나 클래스 A에 대한 객체가 전혀 생성되어 있지 않으므로 클래스 외부에서 이 함수에 접근할 때는 이 함수 내에 $this 객체를 사용해서는 안됩니다. 물론 일반 함수와 마찬가지로 지역 변수 및 전역 변수를 사용할 수는 있습니다.

class A {
  var $var = "초기값";

  function example() {
    echo "클래스 A에 속한 메쏘드 example. <BR>\n";
    echo $this->var . "<BR>\n";
  }
}

A::example();

위의 예제를 보면 아직 클래스 A에 대한 객체가 생성되지 않았으므로 멤버변수 $var에 대한 기억장소가 할당되지도 않았고 더구나 초기값을 설정할 수도 없습니다. 그러니 아무리 범위연산자를 이용하여 메쏘드 example()에 접근한다해도 멤버변수 $var의 초기값을 나타낼 수는 없을 것입니다. 실험해 본 바로는 이 경우 $this->var의 값이 NULL로 처리되는 것 같습니다.

부모클래스의 메쏘드에 접근할 때

class A {
  function example() {
    echo "클래스 A에 정의된 메쏘드 example. <br>\n";
  }
}

class B extends A {
  function example() {
    echo "클래스 B에서 재정의된 메쏘드 example. <br>\n";
    A::example();
  }
}

$b = new B;

$b->example();

이 예의 출력결과를 보면 아래와 같이 나타날 것입니다.

클래스 B에서 재정의된 메쏘드 example.
클래스 A에 정의된 메쏘드 example.

범위연산자는 클래스가 상속되었을 때 재정의되기 전의 부모클래스에 있는 메쏘드에 접근할 때 유용하게 사용될 수 있습니다.

부모클래스의 멤버변수에 접근할 때

php.net의 문서 설명과는 달리 아직 공개되지 않는 어떤 방법이 있는 지는 모르겠으나 부모클래스의 멤버변수로 접근하는 방법에 대하여는 문서화되지 않은 것 같습니다.

6. 부모키워드


부모클래스의 메쏘드 호출

보통 부모클래스에서 선언된 메쏘드를 자식클래스에서 재정의하는 이유는 크게 두가지가 있습니다.

1. 부모클래스 메쏘드를 완전히 새롭게 정의하기 위하여
2. 부모클래스 메쏘드의 기능에 새로운 기능을 추가하기 위하여

첫번째 기능은 부모클래스의 메쏘드를 무시하고 메쏘드에 새로운 정의를 함으로써 부모클래스의 메쏘드 정의를 숨기는 것입니다. 그러나 때로는 부모클래스의 메쏘드를 모두 지우는 것보다는 추가적인 기능이 필요한 경우가 있습니다. 이같은 경우에는 부모클래스의 메쏘드와 자식클래스에서 재정의된 메쏘드를 모두 수행하게 될 것입니다. 즉, 재정의된 메쏘드 구문 내에서 부모클래스의 메쏘드를 호출할 수 있어야 하며 필요한 기능만 추가적으로 작성하면 될 것입니다. 이럴 때 부모클래스의 메쏘드를 호출하기 위해서 사용하는 키워드가 parent입니다. 자바에서의 키워드 super와 같은 역할을 하며 이것은 그 메쏘드 호출을 상위클래스로 전달합니다.

부모키워드 parent는 $this 키워드와 비슷하게 이 클래스의 부모클래스를 나타내는 위치 지정자입니다. 현재 클래스의 부모클래스를 참조해야 되는 경우에는 부모키워드 parent를 사용할 수 있습니다.

class A {
  function example() {
    echo "클래스 A에 정의된 메쏘드 example. <br>\n";
  }
}

class B extends A {
  function example() {
    echo "클래스 B에서 재정의된 메쏘드 example. <br>\n";
    parent::example();
  }
}

$b = new B;

$b->example();

이 예의 출력결과를 보면 아래와 같이 나타날 것입니다.

클래스 B에서 재정의된 메쏘드 example.
클래스 A에 정의된 메쏘드 example.

앞장 범위연산자에서 설명한 대로 키워드 parent 대신에 extends 다음에 기술된 부모클래스명을 직접 사용해도 됩니다.

parent::example(); ------> A::example();

키워드 parent를 써야 될 이유

위의 예에서 부모클래스를 A가 아닌 A1으로부터 상속받도록 수정하여야 한다면 아래와 같이 extends 다음에 있는 부모클래스명을 변경하는 것으로 모든 작업은 끝나게 됩니다. 만약 parent::example()가 아닌 A::example()라고 작성하였었다면 이 부분도 A1::example()라고 수정하여야 할 것입니다. 결국 수정할 때 손이 더 많이 가야 하는 것이지요. 그러니 부모클래스에 있는 메쏘드에 접근하는 경우라면 키워드 parent를 이용하는 것이 소스 코드를 관리하는데 훨씬 유리할 것입니다.

class B extends A1 {
  function example() {
    echo "클래스 B에서 재정의된 메쏘드 example. <br>\n";
    parent::example();
  }
}

$b = new B;

$b->example();
7 매직함수


__sleep, __wakeup과 같이 "__"로 시작하는 매직함수(magic function)는 PHP 클래스 내에서 특수한 목적으로 사용됩니다. 따라서 이 함수들이 가지고 있는 문서화된 매직 기능을 사용할 필요가 없다면 클래스 내에 이 함수들을 정의해서는 안됩니다.

__sleep

serialize 함수를 통해 객체를 직렬화할 때 해당 클래스에 매직 함수 __sleep가 정의되어 있는지 확인합니다. 만약 정의되어 있다면 객체를 직렬화하기 전에 __sleep 함수를 수행합니다. 이 함수는 직렬화하기 전에 객체 멤버에 대하여 조작해야 하는 작업, 또는 직렬화하기 전에 미리 수행해야 하는 작업(예를 들어 데이터베이스 연결 종료 등)을 수행할 수 있습니다. __sleep 함수는 직렬화할 객체의 모든 멤버변수의 이름을 변수에 담아 반환합니다.

class Scott {
  var $error;
  var $svar = array();

  function Scott() {
    $this->svar['Hello'] = "World";
  }

  function __sleep() {
    $this->svar['Hello'] = "Yawn";
    // return list of instance-variables to be serialized
    return array('error', 'svar');
  }
}

$x = new Scott();
print_r($x);
$y = serialize($x);
$z = unserialize($y);
print_r($z);

__wakeup

unserialize 함수를 통해 문자열을 객체화할 때 해당 클래스에 매직 함수 __wakeup가 정의되어 있는지 확인합니다. 만약 정의되어 있다면 객체화하기 전에 __wakeup 함수를 수행합니다. 이 함수를 수행할 때 객체화하기 전에 객체를 상대로 수행해야하는 작업, 또는 객체화하기 전에 미리 수행해야 하는 작업(예를 들어 데이터베이스 연결 등)을 수행할 수 있습니다.

class Scott {
  var $error;
  var $svar = array();

  function Scott() {
    $this->svar['Hello'] = "World";
  }

  function __sleep() {
    $this->svar['Hello'] = "Yawn";
    // return list of instance-variables to be serialized
    return array('error', 'svar');
  }

  function __wakeup() {
    $this->svar['test'] = "I'm here!";
  }
}

$x = new Scott();
print_r($x);
$y = serialize($x);
$z = unserialize($y);
print_r($z);

__call


PHP5에서 새로 추가된 __call이라는 매직함수이다.
일반적으로 클라스 내에 메소드를 호출할경우 호출 함수가 없을 경우는 에러가 발생한다.
그러나 __call 이라는 매직함수는 이런 에러를 체크하여 다시금 메시지를 띄워준다.
<?
class override{

	function say(){
		echo "say blah\n";
	}

	function __call($func, $args) {//호출되는 메소드가 없을 경우
		echo "func : ", $func;
		echo ", arg:", implode(",", $args)."\n" ;
	}
	
}
 

$o = new override();
$o->say();
$o->none_func("123", "456", "789");
$o->say_again("what?");
?>
결과
say blah
func : none_func, arg123,456,789
func : say_again, argwhat?

__set __get


<?
class setget extends ArrayObject{

	public function __set($name, $val) {
        $this[$name] = $val;
    }

	 public function __get($name) {
        return $this[$name];
    }

}
 
$c = new setget();
$c->age = "too young";
$c->name = "pondol";
echo $c->age;
echo $c->name;
?>
결과
too young
pondol
참 재미나는 결론이다. set, get은 함수에 들어오는 특정한 값을 받았다가 다시 리턴 시켜주는 것이다.
그러나 이런 것은 타 언어로 부터의 특징이다. 가령 다른 언어들은 변수의 타입을 정의해 주어야 하므로 이렇게 처리하지 않으면 에러가 발생한다.
하지만 php에서는 변수타입없이 처리되므로 바로 사용하여도 상관없다.
그러나 꼭 필요한 경우도 있으므로 알아두시기 바랍니다.
<?
class setget extends ArrayObject{
}
 
$c = new setget();
$c->age = "too young";
$c->name = "pondol";
echo $c->age;
echo $c->name;
?>
set get없이도 상단과 같은 동일 결과를 얻을 수 있다.
8. 간단한 예제


1. 현재 시간을 받아서 Universal Time과 StandardTime으로 디스플레이하기

       <?
         class Time {
         function UniversalTime() {
         return sprintf("%02d:%02d:%02d", $this->hour, $this->minute,
         $this->second);
         }
       function StandardTime() {
         return sprintf("%02d:%02d:%02d %s", (($this->hour % 12
         == 0) ? 12 : $this->hour % 12), $this->minute, $this->second,
         ($this->hour < 12 ? "AM" : "PM"));
         }
         }
       $timeClass = new Time();

$timeClass->hour = date("H"); $timeClass->minute = date("i"); $timeClass->second = date("s"); echo "UniversalTime = ".$timeClass->UniversalTime(); echo "StandardTime = ".$timeClass->StandardTime(); ?>

9. 추상 클라스


상위 클라스에서는 메소드만 구현해 두고 하위 클래스에서 그 메소드에 대한 값들을 각각 구현하는 것이다.
또한 추상 클라스는 php5 이상 부터 가능하다.
추상 클라스를 사용하는 이유 : 왜 추상 클라스를 사용할까? 프로그램을 하다보면 기본적으로 정의되어야 하는 것이 많습니다.
가령 남자와 여자라는 클라스를 정의한다고 했을때
남자 : 눈2개, 코1개, 귀2개, .... 서서 일을 함(?)
여자 : 눈2개, 코1개, 귀2개,.... 않아서 일을 함(?)
이라는 공통점을 많이 가져갑니다. 그리고 다른것은 몇개없죠
이럴경우 상위에 인간 이라는 클라스(추상클라스)를 하나 두고
인간 : 눈2개, 코1개, 귀2개....
남자 : 서서 일을 함
여자 : 않아서 일을 함
이라고 정의를 한다면 상당히 많은 키보드의 노고를 들수 있을 겁니다. 아이, 여자아이, 남자 아이가 출현한다고 해도 인간이라는 부모로 부터 쉽게 확장할 수 있습니다.
또한 가장 중요한 객체 지향적인 프로그램이 가능합니다.


아래 예를 보면서 설명드리겠습니다.
아래에서 보면 abstract, protected, public 이란는 키워드가 사용되었습니다.
abstract : 추상 클라스
protected : 클라스 내부에서만 참조가능(이곳에서 echo 문과 같은 출력문은 허용되지 않는다)
public : 일반적인 함수(이것이 생략되면 일반적으로 public 이다)

추상 클라스에서는 하나 이상의 추상(abstract)메소드(흔히 함수)를 지니게 된다.
이 추상메소드는 자식(하위의 동일) 메소드를 반드시 참조하게 된다.
<?
abstract class myChoice{
   abstract protected function getcolor();

	function say(){
		echo $this->getcolor()."\n";
	}
	
}
 
class Red extends myChoice{
    protected function getcolor(){
		return "red";
    }

}
 
class Blue extends myChoice{
   protected function getcolor(){
        return "blue";
    }

	public function saymore(){
		echo "i like ".$this->getcolor();
	}

}
 
$color1 = new Red();
$color1->say();

$color2 = new Blue();
$color2->say();
$color2->saymore();
?>

Powered by shop-wiz since 2002, e-mail:master@shop-wiz.com