목차
~~Title:PHP 클래스~~
OO PHP
클래스 선언
class MySample { public $var1; function func1() {} } // ';' 는 필요 없나? -> 없어도 된다.
생성자,소멸자
class MySample { public $var = 'class attribute'; //생성자 function __construct( /* param if need */ ) { echo 'construct'.'<br/>'; } //소멸자 function __destruct() { echo 'destruct' . '<br/>'; } }
인스턴스
$mySamp = new MySample;
이름으로 생성 할 수도 있다. 변수 이름을 대입해서 사용하는 변수로서.
$MySample = 'MySample'; $mySamp2 = new $MySample;
클래스 속성(Attribute) 사용
클래스 속성을 사용하려면,
class MySample { public $var = 'class attribute'; //... function foo() { echo $this->var; } } $a = new MySample; echo $a->var;
get(), set()을 사용해서, 속성을 사용할 때 데이터를 캡슐화 할 수 있다.
class MySample { public $var2 = 'a'; function __get( $name ) { return $this->$name; } function __set( $name, $value ) { $this->$name = $value; } }
어디에 쓸 것인가, 각 속성이 사용되는 시점에 데이터의 정합성을 확인하는 용도가 있다라고 하는데.. 익숙하지 않은 개념이라 잘 모르겠다.
클래스 연산(operator)
따로 적을 필요 있나..
(class instance)->(operator(...));
상속
키워드 : extends 로 상속 받는다.
class MySample2 extends MySample { public $var3; }
오버라이딩
연산자(operator) 이름이 같다면, 오버라이딩은 기본이다.
자식 클래스 쪽의 오버라이딩된 함수에서 부모의 함수를 호출하려면 parent::를 붙여서 호출하면 된다.
class A { function operA() { echo 'from a'; } } class B { function operA() { echo 'from b'; parent::operA(); } }
final
연산자에 final을 붙이면, 오버라이딩이 되지 않는다.
class MySample { final function operA() {} }
class 에 final을 붙이면 상속이 되지 않는다.
final class MySample { //... }
이 두 경우 모두 실행하면 에러가 발생된다.
다중 상속
지원하지 않는다.
인터페이스
자바의 인터페이스와 같다. 클래스의 인터페이스를 만든다.
interface Displayable { function display(); }
사용하려면,
class SomePage implements Displayable { function display() { // .. } }
php 고급 객체 지향 기능
클래스당 상수
정적(static) 메소드
static 을 붙이면 인스턴스를 만들지 않아도 호출이 가능하다.
class Math { static function squared( $input ) { return $input * $input; } } // 사용하기 echo Math::squared(2);
클래스 타입검사와 hinting
instanceof
- 특정 클래스의 인스턴스인가
- 특정 클래스를 상속 받았는가?
- 인터페이스를 구현한 것인가?
판단하는 키워드.
if( $b instanceof A ) // $b는 A의 무엇인가에 따라 리턴 값이 true , false가 나온다.
힌팅
// if class B가 있다면 function check_hint( B $someclass ) { //... }
함수 파라미터에 클래스 이름을 적어서, 다른 종류의 클래스 인스턴스를 받는 것을 막는다.
정적 바인딩
정적 함수에 대한 오버라이딩 기능이 적용된다. php v5.3 부터 적용.
class A { public static function who() { echo __CLASS__; } public static function test() { static::who(); } } class B extends A { public static function who() { echo __CLASS__; } } B::test(); // 결과는 B
객체복사
clone 명령어로 복사
$c = clone $b;
직접 복사하는 기능을 추가하는 경우, __clone()함수를 정의하여 필요한 부분을 넣는다.
clone 을 실행해도 , 완전히 똑같이 복사본을 만드는 기본 행동 뒤에 __clone()가 호출되므로, 전체를 다시 복사하지 않아도 된다.
추상 클래스
인터페이스 클래스가 있는데 이건 왜 만들었을까? abstract와 같이 사용해서 추상 클래스를 만든다. 내부 메소드도 추상 여부에 대한 키워드를 추가할 수 있다.
abstract class A { abstract function operationX( $param1, $param2 ); }
__call() 메소드 오버로딩
흥미로운 기능이다. 오버로딩 기능 중에 유용하게 쓸 수 있을 것 같다.
첫번째 파라미터는 호출되는 메소드 이름.
두번째는 호출되는 메소드에 넘어갈 파라미터의 배열이다.
//예제함수 public function __call( $methodName, $param ) { if( $methodName == 'display' ) { if( is_object($param[0]) ) $this->displayObject( $param[0] ); else if( is_array($param[0]) ) $this->displayArray( $param[0] ); else $this->displayScala( $param[0] ); } } //사용 예 $ov = new overload; $ov->display( array(1,2,3) ); // call displayArray() $ov->display( 'cat' ); // call displayObject()
display()라는 메소드를 호출하면 __call() 메소드가 실행 되고, __call() 내부에서는 display() 메소드가 호출되는 경우에 대한 코드가 실행 된다. 그 코드에서는 파라미터에 따라 각각 다른 함수를 부르는 부분이 실행된다. 약간의 오버로드는 예상되지만.. 복잡한 실행 구조를 감추는 편의 함수를 작성할때 요긴할 것 같다.
display()는 구현할 필요가 없다.
__autoload
클래스에서 사용하는 함수가 아니라 독립된 함수로서, __autoload()를 구현하면 클래스를 생성하려고 할때 자동으로 호출된다.
new 연산자를 오버로딩한 것 같은 효과?
필요한 클래스의 인스턴스를 만들때, 클래스가 선언된 파일을 불러 오는 용도로 주로 사용한다고 한다.
function __autoload( $name ) { include_once $name . ".php"; }
Iterator와 반복 구현하기
배열처럼 클래스 속성에 접근할 수 있다? (정말로?)
class myClass { public $a = '5'; public $b = '3'; public $c = '3'; } $x = new myClass; foreach( $x as $attribute ) { echo $attribute . '<br/>'; }
이것보다 복잡한 방식이라면, iterator를 만들어야 한다.
예제코드가 길기때문에 패스. 필요하면 인터넷 검색.
클래스를 문자열로
$p = new someclass; echo $p;
__toString() 함수를 클래스에 구현하면, 클래스를 출력할때 (위의 코드) 이 함수가 호출 된다.
class Printable { public $test1; public $test2; public function __toString() { return (var_export($this, TRUE)); } }
reflection API
디버깅용인가?
<?php require_once('page.inc'); $nc = new ReflectionClass('Page'); echo '<pre>' . $nc . '</pre>'; ?>
해당 클래스, 여기에서는 Page,의 상세 정보가 쭈욱 출력된다.
7장 - 예외처리
try { //code throw new Exception('msg',code); } catch( Exception $e ) { //예외처리 }
Exception Class
Exception class의 기본 메소드
- getCode()
- getMessage()
- getFile()
- getLine()
- getTrace()
- getTraceAsString()
- __toString() : 이 함수를 구현하면, Exception 클래스를 바로 출력할때, 필요한 정보만 줄 수 있다.
디버깅 클래스를 따로 만드는 것이 낫지 않나?