2014-04-09
언젠가 한번 PHP의 CLASS에 대해서 대충 포스팅 한 적이 있는데.. PHP공식 홈페이지의 클래스에 관한 부분이 바뀌어 버렸다. 그런데 그때 해당 페이지들을 따로 모아놓질 않아서, 이번에 새로 CLASS에 대해서 포스팅을 할려니... 역시 양이 많고...
그래서, 잘 정리해놓은 것을 찾아서 가져왔다.

기본적으로 CLASS 라는것은 어떤 언어에서든지 비슷한 방식과 개념을 가지고 있기 때문에, PHP라고 해도 기본적인 것들은 크게 다르지 않다. 다만 PHP가 5.x 버전 부터는 생성자를 CLASS 이름과 같은 함수명이 아닌 __construct()로 사용하도록 바뀌었다는 것과( 참고 : http://php.net/manual/kr/language.oop5.decon.php) 여전히 다중상속(한번에 2개이상의 CLASS를 상속하는 것)은 지원하지 않는다는 점은 알아두길 바란다.
참조 페이지
http://hyeonstorage.tistory.com/115
http://hyeonstorage.tistory.com/116


삭제 대비용 원본글 복사

객체지향 언어(OOP, object-oriented programming)이 발전하면서, 함수 이상으로 코드를 재사용할 수 있게 되었다. 객체를 통해서 데이터를 요청하고, 객체를 통해서 데이터를 받아온다. 각각의 객체는 각각의 역할에 따른 데이터를 가지고 기능을 수행한다. 객체를 통해 코드를 재사용하면서, 적은 코드로 효율적인 프로그래밍이 가능해졌다.

객체를 사용하는 프로그램을 만들 때는 데이터와 코드의 합성인 클래스를 디자인 해야 한다. 이 클래스에 기반한 새 객체를 클래스의 인스턴스(instance)나 어커런스(occurrence)라고 한다.

 

클래스 정의

 

객체는 class 키워드로 클래스를 정의한다. 클래스의 정의에는 클래스 이름(대소문자 구분)과 속성, 메소드가 포함된다.

클래스는 데이터를 저장하는 속성 값을 가지고 있으며, 데이터를 가공/처리 하기 위한 메소드를 포함한다.

 

 

 

 

<?php
  
   class User{     // User 클래스 선언
        
        public $id$email$name$birthday;  //public으로 변수 선언
 
        function printUser(){   // User 클래스에 printUser 메소드 선언
            print_r($this);      // User 클래스 Print
        }
    }
 
?>
 

print_r 함수는 객체의 정보를 출력해준다. 변수에 대입된 값이 없을때 printUser() 함수를 실행하면

User Object([id] =>   [email] =>   [name] =>    [birthday] =>  )    가 출력된다.

 

객체  생성

 

객체를 생성하려면 new 키워드를 사용한다.

 

 

<?php
  
   $object = new User;     // new 키워드로 User 객체를 생성한다.
 
   class User{     // User 클래스 선언
        
        public $id$email$name$birthday;  //public으로 변수 선언
 
        function printUser(){   // User 클래스에 printUser 메소드 선언
            print_r($this);      // User 클래스 Print
        }
    }
 
?>

객체 접근

 

객체의 속성에 접근하는 방법은 -> 를 사용하는 것이다.

new로 생성한 User 클래스를 대입한 $object의 name 속성에 접근하기 위해서는

 

$object->name 

 

또는 객체의 메소드인 printUser()에 접근하기 위해서는

 

$object->printUser();  

 

이다.

속성이나 메소드에 접근할때는 $ 표시를 붙이지 않도록 주의해라. $를 붙이면 해당 변수를 가르키기 때문에 의도하지 않은 접근이나 오류를 발생시킬 수 있다.

 

만약 $name에 "Hyun"이 대입되어 있을때,  $object->$name 을 사용하면,

$name은 "Hyun" 이기 때문에 $object->Hyun 이 된다.

$object(User 클래스)의 속성에는 Hyun이 없기 때문에 에러가 발생한다.

 

 

<?php
  
   $object = new User;     // new 키워드로 User 객체를 생성한다.
 
   $object->printUser();  // 비어있는 User 객체 출력
 
   $object->id = "3"// User 객체의 id 속성에 3 대입
 
   $object->name = "Hyun";  // User 객체의 name 속성에 Hyun 대입
 
   $object->printUser();  // User 객체 출력 User object( [id]=>3 [email]=> [name]=>hyun [birthday]=>)
 
   class User{     // User 클래스 선언
        
        public $id$email$name$birthday;  //public으로 변수 선언
 
        function printUser(){   // User 클래스에 printUser 메소드 선언
            print_r($this);      // User 클래스 Print
        }
    }
 
?>

 

객체 복제

 

new로 객체를 생성하여 매개 변수로 넘길 때는 참조로 넘어간다. 따라서 새로운 메모리를 할당하는 것이아닌 객체의 주소값을 전달하는 것이다. 다시 말해서 객체를 대입하는 것은 전체를 복사하는 것이 아니다.

참조로 주소값을 전달하면, 같은 메모리의 인스턴스를 사용하기 때문에 한쪽에서 객체의 속성에 접근하여 값을 변경하면, 다른 변수에서 해당 속성에 접근해도 같이 변경되어 있다.

새로운 객체의 복제를 원한다면 clone 키워드를 사용하면 된다.

 

 

<?php
 
   $object1 = new User();         // User 객체 생성하여 object1 변수에 대입
 
   $object1->name = "Hyun";     // object1 객체의 name 속성에 Hyun 대입
 
  $object2 = $object1;              // object1 객체의 참조값 object2에 대입
 
  $object2->name = "Rang";     // object2 객체의 name 속성에 Rang 대입
 
  
  echo "object1 name = " . $object1->name . "<br>";     // Rang 출력
 
  echo "object2 name = " . $object2->name . "<br>";    // Rang 출력
 
 
  $object3 = clone $object1;                   // object1 객체를 복제하여 object3에 대입
 
  $object3->name = "Ten";                     // object3 객체의 name 속성에 Ten 대입
 
 
  echo "object1 name = " . $object1->name . "<br>";    // Rang 출력
 
  echo "object3 name = " . $object3->name . "<br>";    // Ten 출력
 
 
  class User{     // User 클래스 선언
        
        public $id$email$name$birthday;  //public으로 변수 선언
 
        function printUser(){   // User 클래스에 printUser 메소드 선언
            print_r($this);      // User 클래스 Print
        }
    }
?>

 

 

생성자 __construct()

 

새로운 객체를 생성할 때 매개 변수의 리스트를 호출되는 클래스로 전달할 수 있다.

이것은 여러 가지 속성을 초기화하는 생성자(Constructor)라고 하는 클래스 내에 특별한 메소드로 전달된다.

생성자는 __construct() 를 메소드 이름으로 사용한다.

 

 

<?php
 
  $object = new User();                  //  User 객체 생성하면서 __construct() 함수 실행
 
  echo $object->name;            //  Hyun 출력
 
 
   
  class User{     // User 클래스 선언
        
        public $id$email$name$birthday;  //public으로 변수 선언
 
        function __construct(){       // 생성자 선언
            
            $this->name = "Hyun";     // 객체가 생성되면서 name 속성에 Hyun 대입   
        
        }
        function printUser(){   // User 클래스에 printUser 메소드 선언
            print_r($this);      // User 클래스 Print
        }
    }
?>

 

소멸자 __destruct()

 

PHP 코드가 마지막 참조를 하고 났을 때나 스크립트가 끝에 도달한 경우 소멸자를 실행하며, 객체를 해제한다.

소멸자 메소드는 __destruct() 로 명명한다.

 

 

<?php
 
  $object = new User();                  //  User 객체 생성
 
  echo $object->name;            //  Hyun 출력
 
 
   
  class User{     // User 클래스 선언
        
        public $id$email$name$birthday;  //public으로 변수 선언
 
        function __construct(){       // 생성자 선언
            
            $this->name = "Hyun";     // 객체가 생성되면서 name 속성에 Hyun 대입   
        
        }
        
        function __destruct(){
        
           echo "User 객체 소멸";    
        
        }
        
        function printUser(){   // User 클래스에 printUser 메소드 선언
            print_r($this);      // User 클래스 Print
        }
    }
?>
 

 

 

1.메소드

 

$this 는 현재의 객체에 접근할 때 사용한다. $this를 사용해서 현재 객체의 속성 또는 함수를 호출한다.

 

 

<?php
 
    $object = new User();            // User 객체 생성
    
    $object->name = "Hyun";       // name 속성에 Hyun 대입
    
    echo $object->get_name();    // Hyun 출력,  User 객체의 get_name() 함수 실행 
  
   
     class User{                      // User 객체
        
        public $id$name
         
        function get_name(){
        
            return $this->name;         // 현 객체(User)의 name 속성 값 반환    
            
        }
?>

 

 

PHP5에서는 객체로부터가 아닌 클래스로부터 호출되는 정적(static) 메소드를 정의할 수 있다. 정적 메소드는 어떤 객체 속성에도 접근성을 갖지 않는다.

정적메소드의 호출은 -> 가 아닌 더블콜론(::)으로 호출된다.

정적메소드는 객체가 아닌 클래스로 부터 호출된다.

 

 

<?php
 
    User::name_string();                 //  Your name is Hyun 출력
                                                //User 클래스의 static형 name_string() 출력
    
    
    class User{
        
        static function name_string(){             // static 형 name_string 메소드 선언
            
            echo "Your name is Hyun";            // "Your name is Hyun 출력
            
         }
        
    }
?>

 

 

2. 속성 선언

 

속성은 처음 사용될 때 암묵적으로 정의할 수 있기 때문에 클래스 밖에서 선언할 수도 있다. 객체를 생성 후에 속성을 추가적으로 선언할 수 있지만, 좋은 코딩 방법이 아니다. 가독성과 유지보수를 위해서는 클래스 내에서 속성을 선언하는게 좋다.

아래와 같은 코드는 정상적으로 실행되지만, 좋은 코딩 방법이 아니다.

 

 

<?php
 
    $object = new User();                //  User 객체 생성
                                               
    $object->name = "Hyun";          // User 객체에 name 속성 선언 후 Hyun 대입
    
    echo $object->name;               // Hyun 출력
    
    class User{
        $id;
    }
?>


클래스 내에서 속성을 정의할 때 초기 값을 대입한다. 이때 값은 상수여야 하고, 함수나 표현식의 결과는 안된다.

 

 

<?php
    
    class User{
        
        public $id = "abc";      // 유효함
        
        public $name = "Hyun";   // 유효함
        
        public $age = calcAge();    // 무효함 - 함수 호출
         
        public $score = $level *2;   // 무효함 - 표현식 사용
    }
?>

 

 

3. 상수 선언

 

define 함수로 전역 상수를 정의한 것과 같은 방법으로 클래스 내에 상수를 만들 수 있다.

클래스 내에서 상수는 const 로 선언하며, 호출시에는 self 키워드와 더블콜론(self::)로 직접 참조된다.

상수는 한번 정의하면 바꿀 수 없다.

일반적으로 상수 정의는 대문자로 한다.

 

 

<?php
     Translate::lookup();     // 1 출력 ; Transalte 클래스의 static형 함수 lookup() 호출
    
    class Translate{
        
        const ENGLISH = 0;       // 상수로 Englich = 0 선언
        
        const SPANISH = 1;       // 상수 선언
        
        const FRENCH = 2;        // 상수 선언
        
        const GERMAN = 3;       // 상수 선언
        
        
        static function lookup(){      // static 형 lookup 함수 선언
            
            echo self::SPANISH;        // 1 출력; 클래스의 상수 SPANICH 참조
            
        }
?>

 

 

4. 속성과 메소드 범위

 

PHP5는 속성과 메소드 범위를 제어하는 데 public, protected, private 를 제공한다.

 

public

var나 public 키워드를 사용해 변수를 정의할 때나 변수가 처음 사용되는 시점에 암묵적으로 정의될 때 이런 속성은 기본이다. var는 더 이상 사용하지 않지만 PHP에서 이전 버전과 호환성을 위해서 남겨져 있기 때문에 var와 public은 상호 교체 가능하다. 메소드는 기본으로 public을 가정한다.

 

protected

여기서 속성과 메소드는 객체의 클래스 메소드와 서브클래스의 메소드에서만 접근 가능하다.

 

private

여기서 멤버는 서브클래스는 안 되고, 같은 클래스 내의 메소드에서만 참조 가능하다.

 

 

public, protected, private 선택

- 해당 코드 외부에서 이 멤버에 접근해야 할 때와 서브클래스에서 상속받을 때 public을 사용한다.

- 해당 코드 외부에서 이 멈베어 접근하면 안 되지만, 서브클래스에서 상속받아야 할 때 protected를 사용한다.

- 해당 코드 외부에서 접근해서도 안 되고, 서브클래스에서도 상속받으면 안 될때 private를 사용한다.

 

 

<?php
     
    class Example{
        
        var $name = "Hyun";    // public과 같지만 사용하지 않음
        
        public $age = "29";     // public 속성
        
        protected $location;   // protected 속성
        
        private function admin(){   // private 메소드
            
        }
?>

 

 

5. 상속

 

클래스를 만들면 서브클래스를 파생할 수 있다. 서브클래스를 사용하면 힘들게 코드를 다시 작성해야 하는 일을 어느 정도 피할 수 있다.

이럴때 extends 연산자를 사용해 상속을 할 수 있다.

extends를 사용하여 확장하면 서브클래스에서 부모 클래스의 속성을 사용할 수 있다.

 

 

<?php
     
    $object = new Subscriber;               // Subscriber 객체 생성
    
    $object->name = "Hyun";                 // name 속성에 Hyun 대입
    
    $objcet->password = "abc123";        // password 속성에 abc123 대입
    
    $bojcet->display();                  // Name : Hyun   Pass : abc123  출력    
                                                  // Subscriber 객체의 display 함수 실행
    
    
    class User{                // User 객체
        
        public $name;          
        
        function save_user(){
            
            echo "Save User code goes here";
            
        }
   }
        
     class Subscriber extends User{              // User 객체를 상속한 Subscriber 객체
        
        public $password;
        
        function display(){
            
            echo "Name : " . $this->name . "<br />";     // 상속받은 User 객체의 name 변수 접근
            echo "Pass : " . $this->password;
            
        } 
     } 
?>

 

 

부모 연산자

 

부모 클래스에서 사용한 것과 같은 이름으로 서브클래스의 메소드를 정의하려고 하면, 부모 클래스의 메소드를 대체한다.

하지만 가끔 부모클래스의 메소드에 접근해야 한다. 이때는 parent(parent::) 연산자를 사용한다.

자신의 클래스의 메소드를 호출할 때는 self(self::)를 사용한다.

 

 

<?php
     
   $object = new Son;                 // Son 객체 선언
 
   $object->test();                      // [Class Son] I am Luke 출력
 
   $object->test2();                    // [Class Dad] I am your Father
 
   $object->test3();                    // [Class Son] I am Luke 출력
 
 
 
   class Dad{                             // Dad 클래스
    
       function test(){                    // test 메소드
        
          echo "[Class Dad] I am your Father<br/>";    //[Class Dad] I am your Father 출력
        
       }
    }
    
   class Son extends Dad{              // Dad 객체를 상속한 Son 클래스
    
       function test(){              // test() 메소드
        
           echo "[Class Son] I am Luke<br/>";   // [Class Son] I am Luke 출력
        
       }
    
       function test2(){                // test2() 메소드
        
           parent::test();               // [Class Dad] I am your Father 출력
                                             // 부모 Dad 의 test() 메소드를 실행한다.   
        }
        
       function test3(){               // test3() 메소드
        
           self::test();                  // [Class Son] I am Luke 출력
                                            // 현재 클래스(Son)의 test() 함수 실행
        }
     }
        
?>

 

 

서브 클래스 생성자

 

클래스를 확장하고 생성자를 정의할 때 PHP는 자동으로 부모 클래스의 생성자 메소드를 호출하지 않는다. 모든 초기화 코드가 확실히 실행되려면 서브클래스는 부모의 생성자를 호출해야 한다.

 

 

<?php
     
   $object = new Member();      // Member 객체 생성
 
   echo $object->gender;          // Man 출력    
 
   echo $object->name;             // Hyun 출력
 
 
   class User{                         // User 클래스
       
       public $gender;                // gender 속성
    
       function __construct(){          // User 클래스 생성자
        
           $this->gender ="Man";      // gender 속성에 Man 으로 초기화
        
        }
    }
    
    class Member extends User{      // User 객체를 상속한 Member 클래스
    
       public $name;                      // name 속성 선언
    
       function __construct(){           // Membere 객체 생성자
    
          parent::__construct();          // 부모(User) 객체의 생성자 실행
        
          $this->name ="Hyun";           // name 속성에 Hyun 대입
      }
    
   } 
 
?>

 

Final 메소드

 

서브클래스가 슈퍼클래스의 메소드를 대체하는 것을 원하지 않을 경우 final 키워드를 사용한다.

 

 

<?php
     
   class User{
    
       final function copyright(){
        
         echo "This class was written by Joe Smith";
        
       }
   }
?>