미운오리스키 님 박달나무 님 께 바칩니다. > 자유게시판

자유게시판

미운오리스키 님 박달나무 님 께 바칩니다. 정보

미운오리스키 님 박달나무 님 께 바칩니다.

본문

어제 코드는 유익하였습니다. 저 나름대로도 무슨 코드일까 하고 봤다가 오버로딩인가 오버라이딩인가 (사실 큰 의미는 없습니다만) 하고 생각도 해보고 나름대로  오버로딩 오버라이딩 이야기도 하면서 다시 한번 찾아보게 되는
저에게도 매우 유익한 시간이였습니다.
제가 아는게 틀렸을까봐 더 많이 공부하게 해주기도 하였네요.
어제 제가 링크 올려두고 세부적으로 설명을 안한 부분에 대해 무언가 의견을 공유하고 배워가고 싶은 마음에
불러봅니다.

PHP 에는 매직매소드 라는 것이 존재합니다. 
__construct()__destruct()__call()__callStatic()__get()__set(),
__isset()__unset()__sleep()__wakeup(),
__toString()__invoke()__set_state() 그리고 __clone() 등등이 있지요.
그 중 메소드 오버로딩으로 활용되는 __call() 이라는 부분과 __callStatic() 이라는부분이 있는데
제가 예전에 정리 해둔걸로는 다음과 같이 정의 해두었더라구요.

  1. __call()
    1. class 에서 정의 되지 않은 메서드에 접근을 할 때 자동 호출 되는 메소드 (메소드 오버로드)
    2. 앞쪽은 메소드 명이 오고, 뒤쪽은 넘어 오는 파라미터가 배열로 저장이 됨
    3. $params[0] 부터 접근을 할 수 있음
    4. 사용방법은 다음과 같음
      <?php
      
      class people {
      
      public function __call($method, $params) {
       echo "Calling object method : " . $method . "<br />";
       foreach ($params as $key => $value) {
       echo "name : " . $value . "<br />";
       }
       }
      
      }
      
      $people = new people;
      $people -> peopleName('John', 'Tom', 'Bob');
       ?>
      
    5. 결과 : Calling object method : peopleName
      name : John
      name : Tom
      name : Bob
  2. __callstatic()
    1. __call 과 같은 메소드 오버로딩
    2. _call 과 _callstatic 의 차이
      1. __call 은 object context 즉 클래스가 인스턴스화 되어 객체 상태로 존재할 때 호출 됨
      2. __callstatic 은 static context 즉 인스턴스화 되지 않는 상태에서 호출 됨
    3. 사용 방법은 다음과 같음
      <?php
      
      class people {
      
      public function __callstatic($method, $params) {
       echo "Calling object method : " . $method . "<br />";
       foreach ($params as $key => $value) {
       echo "name : " . $value . "<br />";
       }
       }
      
      }
      
      people::peopleName('John', 'Tom', 'Bob');
       ?>
      
    4. 결과 (__call 과 동일) : Calling object method : peopleName
      name : John
      name : Tom
      name : Bob
 이걸 보면서 어제의 코드가 __callStatic 으로 메소드 오버로딩을 한건 또 아닌가 하고 생각해봅니다.
(사실 코드를 안봤으니 모르겠지만 추측이라는 점에서)
한동안 잊고 있었는데 다시 정리한걸 찾아보게 해주셔서 감사합니다.
추천
0

댓글 33개

아 적고나서 보니 카멜케이스 안되있네요 저도 블로그 같은곳에 올리면서 따로 정리 안하고 올렸던걸로 기억합니다. 코드의 오타보다는 내용만 봐주세요
눈이 피곤해 합니다..
오래 전에 클래스로 치장된 PHP게시판을 본 적이 있는데 그 후 신경을 안쓰고 있었거든요...
다시 보게 되니 공부는 해야겠다는 생각이 듭니다.

어제 온라인으로 PHP책을 검색해보니 대부분 초보자용 책들만 즐비한 것 같더라구요..
주말에 서점에 직접 나가 봐야겠습니다..
결론만 딱 띄어서 보자면
어제의 그 코드가
people::peopleName('John', 'Tom', 'Bob'); 이것과 유사하지 않았나 하는 말입니다.
나린위키 http://narinwiki.org  프로그램 만들 떄, 이 __call 메소드란걸 알고 헉! 했었던 기억이 나네요
"아 뭐 이런.. 유들유들한 프로그래밍 랭귀지 같으니라고" 하면서 ㅎㅎㅎ

__call 함수도 그렇고 call_user_function_array 도 그렇고.. 참 .. 편리합니다 ㅎ
저도 매직매소드 참 좋아 합니다. getter setter 만 가지도고 object 운용에 편의를 느끼니까요.
근데 __call 이 많이 들어가는 코드가 된다면 오히려 별도의 자식 클래스를 생성해서
만들어가는 방식이 더 좋아보입니다.
core CLASS 를 하나 만들고 각 기능별 CLASS 에서 extends 해서 사용하는 방식이요
넵 그게 정석이 아닐까 싶네요. __call 함수가 있으면.. 이게.. 분석하기가 참 난해할 수 있으니까요. 그때그때 상황에 따라 달라질수 있어서 좋기도 하면서, 오류나면 난감할 수 도 있고.. 다른사람이 보면 헉! 할수도 있는 ^^;
저도 어제 좀 보니까 간단하게 아래같은 방식으로 처리해도
인자갯수라던가 타입별 처리까지는 가능은 하겠더라구요..
근데 기본적으로 지원되는게 아니라 약간 편법에 가까운...;

function test1(){
  switch(func_num_args()){
  case 1: echo("function1<br>"); break;
  case 2: echo("function2<br>"); break;
  case 3: echo("function3<br>"); break;
  }
}

test1('1');
test1('1','2');


function test2(){
  $a =  gettype(func_get_arg(0));
  if($a=='integer'){
    echo("integer param<br>");
  }else if($a=='string'){
    echo("string param<br>");
  }
}

test2(123);
test2('123');


test1 함수는 인자별 갯수에 따라 case 문으로 처리하면 될듯하고

변수타입에 따라 처리가 달라져야 한다면 test2 함수처럼 쓰면 될듯 하구요..
<?
 function test1() {
  call_user_func_array('_t'.func_num_args(), func_get_args());
 }

 function _t1($arg) {
  echo 'This is _t1() : ' . $arg . '<br/>';
 }

 function _t2($arg1, $arg2) {
  echo 'This is _t2() : ' . $arg1 . ', ' . $arg2 . '<br/>';
 }

 test1('1');
 test1('1','2');
 ?>

요론식으로 ^^.. 재밌네요
어차피 test1 함수만 추가된거니,
그렇게 노가다는 아니지 않을까요? ㅎㅎ 그래도 야메 오버로딩
---------
.. 타입까지 구분하려면.. 함수명이 지저분해지겠네요;;
타입이 뭐뭐 있나 궁금해서 대충 테스트 해봤는데 생각보다 많네요 ㅎㅎ
참고로 float 는 안되는듯 ㅠㅠ

function test2(){
  $a =  gettype(func_get_arg(0));
  if($a=='integer'){
    echo("integer param<br>");
  }else if($a=='string'){
    echo("string param<br>");
  }else if($a=='boolean'){
    echo("boolean param<br>");
  }else if($a=='array'){
    echo("array param<br>");
  }else if($a=='float'){
    echo("float param<br>");
  }
}

test2(123);
test2('123');
test2(true);
test2(array('a'));
test2(0.5);
----

<?
 function t(){
   $types = implode('', array_map(create_function('$item', '$type = gettype($item); return $type{0};'), func_get_args()));
   $func = '_t_'.$types;
   if(function_exists($func)) return call_user_func_array($func, func_get_args());
   echo('ERROR : function does not exist - '. $func.'<br/>');
 }
 function _t_d($double) { echo 'This is _t_d() : ' . $double. '<br/>'; }
 function _t_s($str) { echo 'This is _t_s() : ' . $str. '<br/>'; }
 function _t_i($num) { echo 'This is _t_i() : ' . $num. '<br/>'; }
 function _t_si($str, $num) { echo 'This is _t_si() : ' . $str. ', '. $num . '<br/>'; }
 function _t_ss($str1, $str2) { echo 'This is _t_ss() : ' . $str1. ', ' . $str2. '<br/>'; }
 function _t_iss($num, $str1, $str2) { echo 'This is _t_iss() : ' . $num . ', ' . $str1. ', ' . $str2. '<br/>'; }

 t(0.1);
 t('1');
 t(2);
 t('3', 4);
 t('5', '6');
 t(7, '8', '9');
 ?>

요롷게 해볼 수 있겠는데... gettype 함수 반환값에 float 이 없어서 미운오리스키님 말씀처럼 float 으로는 안되네요 (뭔가 퀴즈 푸는 느낌 ㅎㅎ)
----
설명 부연하면
t() 함수에 파라미터를 넘기면 파라미터들의 타입의 첫 글자들로 _t_타입들() 함수를 호출하게 해봤는데.. 다행히 gettype 함수의 리턴값의 첫 글자들이 다 다르네요 ㅎㅎ
뭔가 잘(?) 처리하면 타입구분도 다 가능할듯 한데요 ㅎㅎ
타입명은 영어만드신분이 잘 만들어 놓으신듯 ㅋㅋ

float 는 찾아보니 is_float 라는 함수가 있네요..
결과값은 double 로...

걍 찍어보니 소수도 걍 double로 체크하면 된다는..
생각해보니 return 이니 else if 가 필요 없어서 또 바꿨습니다.

<?php

class TypeCheck
{

    const PUSH_INT = 'integer';
    const PUSH_STRING = 'string';
    const PUSH_BOOLEAN = 'boolean';
    const PUSH_ARRAY = 'array';
    const PUSH_DOUBLE = 'double';

    public function checkData($param)
    {

        $param = gettype(func_get_arg(0));
        if ($param == TypeCheck::PUSH_INT) {
            return "integer param<br>";
        }
        if ($param == TypeCheck::PUSH_STRING) {
            return "string param<br>";
        }
        if ($param == TypeCheck::PUSH_BOOLEAN) {
            return "boolean param<br>";
        }
        if ($param == TypeCheck::PUSH_ARRAY) {
            return "array param<br>";
        }
        if ($param == TypeCheck::PUSH_DOUBLE) {
            return "float param<br>";
        }
    }

}

$checkData = new TypeCheck();

$a = $checkData->checkData(11111);
$b = $checkData->checkData(1.5);
echo $a . $b;
전체 199,657 |RSS
자유게시판 내용 검색

회원로그인

(주)에스아이알소프트 / 대표:홍석명 / (06211) 서울특별시 강남구 역삼동 707-34 한신인터밸리24 서관 1402호 / E-Mail: admin@sir.kr
사업자등록번호: 217-81-36347 / 통신판매업신고번호:2014-서울강남-02098호 / 개인정보보호책임자:김민섭(minsup@sir.kr)
© SIRSOFT