객체지향 언어(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";
}
}
?>
|