PHP 프로그래밍

본문 바로가기
사이트 내 전체검색


Web Programming >> PHP Programming
[목차]
제22장 PHP에서 클래스 기초 다지기

    1. PHP 클래스 기초

1. 클래스

클래스란 소위 말하는 객체지향 프로그래밍(OOP, Object Oriented Programming)을 보다 직관적으로 할 수 있도록 해주는 PHP 언어의 특징입니다. 따라서 클래스가 무엇인지 알기 위해서는 객체지향 프로그래밍이 무엇인지 알 필요가 있습니다.

매개변수에 따라 정의된 행동을 수행하고, 그 결과값을 되돌려주는 함수를 정의하고 호출하면서 제어되는 프로그래밍 방식을 이미 배웠을 것이다. 이런 함수 중심의 프로그래밍 방식은 프로그램에 나타나는 데이터와 데이터를 조작하는 함수가 분리된 채 코드가 구성되는 데 반해, 객체지향 프로그래밍은 객체(Object)라는 것을 생성하고 생성된 객체를 함께 동작하게 만드는 것에 초점을 맞춰 코드를 진행하는 방식입니다. 그럼 객체의 정체가 궁금하겠군요. 여러분의 관점에서 본 실세계의 사물 혹은 좀 더 추상적인 무엇인가에서 추출한 속성과 행동의 집합을 가진 어떤 형틀을 클래스라고 하며, 이 클래스를 실체화한 것을 객체라고 합니다. 하지만, 이렇게 추상적인 설명만으로는 전혀 감이 잡히지 않을 겁니다. 그럼 여러분도 늘 보는 모니터를 클래스로 표현해 볼까요...

2. 모니터 클래스 표현하기

모니터의 클래스 속성을 보면 일단 제조회사, 모델명, 화면 크기 등으로 생각할 수 있고, 모니터에서 할 수 있는 일로 '전원을 켜다'와  '전원을 끄다'라는 것을 생각할 수 있습니다.

Monitor

+Monitor
+modelName
+screenSize
-Powerstate

+Poweron()
+Poweroff()

모니터는 클래스이고, 실제 '현실 세계에서 생산된 수많은 모니터'가 객체입니다. 그런데 함수에서 정의만 하고 끝나던가요. 정의했으면 함수를 호출하면서 사용해야 의미가 있듯이 클래스 역시 정의만 하면 모든게 끝이 아니라 클래스에 맞는 객체를 생성한 다음 객체를 사용해 코드를 진행해야 합니다. 모니터 공장을 만들었다고 끝이 아니듯 실제 모니터를 생산해야 의미가 있다는 것이겠죠, 이런 클래스와 객체의 차이를 안다면 클래스는 형틀이므로 하나만 있어도 상관없지만, 클래스로부터 찍혀져 나올 객체는 무수히 많을 수 있고, 각각의 객체는 서로 독립적으로 동작하거나 상호작용을 통해 동작할 수 있다는 것도 이해할 수  있을 겁니다. 참고로 이렇게 생성된 객체를 C++에서는 그대로 객체(Object)라 부르고, 자바에서는 인스턴스(Instance)라는 용어로 부릅니다. PHP공식 매뉴얼에서는 둘다 나옵니다. 따라서 ,이 두 개 용어를 다 알 필요가 있습니다. 그럼 예제 코드와 문법 형식을 함께 보면서 클래스에 관련된 문법을 하나하나 파해쳐 볼까요...

3. 클래스 정의하는 방법

클래스를 정의하는 문법을 다음과 같이 나타낼 수 있습니다.

class [클래스 이름] {
  // 인스턴스 변수는 반드시 키워드 var를 붙인다.
  var [인스턴스 변수이름];
  //인스턴스 메쏘드는 일반적인 함수처럼 정의한다.
  function [인스턴스 메쏘드 이름](매개변수들) {
     ;
  }
}

 앞에서 객체는 속성과 행동의 집합을 실체화한 것이라고 말했습니다. 인스턴스 변수는 객체의 속성을 나타내는 것이고, 인스턴스 메쏘드는 객체가 할 수 있는 행동을 나타내기 위한 용어입니다. 혹시 C++ 나 자바 프로그래밍 경험이 있는 독자라면, '클래스 변수나 클래스 메쏘드는 없나요'라고  질문하겠군요. PHP에서는 이런 거창한 것 까지 문법적으로 지원하지 않기 때문에 여기서는 설명하지 않겠습니다. 지금은 일단 인스턴스 변수와 인스턴스 메쏘드의 개념과 문법을 익히는데 치중하세요. 그리고, 앞으로, 특별한 일이 없다면, 인스터스 메쏘드를 간략히 메쏘드라고 부르고, 인스턴스 변수는 그대로 사용하겠습니다.

4. 모니터 클래스 작성

클래스를 정의하는 문법을 배웠으니까, 앞에서 추상화한 모니터 클래스를 실제로 작성해 볼까요.

리스트1 : class.Monitor1.php

<?php

// filename : class.Monitor.php

 

define("ON", "On");

define("OFF", "Off");

 

class Monitor {

 

  var $vendor;

  var $modelName;

  var $screenSize;

 

  var $powerState;

 

  // 생성자

  function Monitor($vendor = "", $modelName = "", $screenSize = "")

  {

    $this->setValue($vendor, $modelName, $screenSize);

    $this->PowerOff();

  }

 

  // 인스턴스가 생성된 다음에 인스턴스 변수를 수정하고 싶을 때 호출한다.

  function setValue($vendor, $modelName, $screenSize)

  {

    $this->vendor = $vendor;

    $this->modelName = $modelName;

    $this->screenSize = $screenSize;

  }

 

  function PowerOn() {

    $this->powerState = ON;

  }

  

  function PowerOff() {

    $this->powerState = OFF;

  }

 

  // 파워가 켜져 있는지 꺼져 있는지를 검사한다.

  function IsOn() {

    if (OFF == $this->powerState)

      return false;

    else

      return true;

  }

 

  // 요구 형식에 맞춰 현재 객체 상태를 출력한다.

  function PrintOut() {

    print "제조사 : " . $this->vendor . "\n";

    print "모델이름 : " . $this->modelName . "\n";

    print "화면크기 : " . $this->screenSize . "\n";

    print "전원상태 : " . $this->powerState . "\n";

  }

}

?>

 

리스트1에서 메쏘드 안에 나타난 '$this->powerState'라는 표현을 보기 바랍니다. C++이나 자바처럼 PHP도 클래스 정의 안에서 인스턴수 변수에 접근하기 위해서 '$this->'라는 표현을 사용하는 것을 볼 수 있습니다. 이런식으로 특정한 메쏘드 안에서 현재의 인스턴스 변수를 조작할 수 있답니다. 또한 '$this->$powerState'라고 작성해서는 안된다는 사실을 꼭 유념하세요. 이런 표현이 문법적으로 틀린 것은 아니지만, 실제로 사용할  때 제대로 동작할 수 있을지는 장담할 수 없습니다. 혹시 변수이름에 대한 변수(Variable Variables)를 알고 있다면 '$this->$powerState'가 어떻게 동작할 지 추측할 수 있겠지요...(PHP강좌의 "PHP에서의 변수"에서 "가변변수 사용하기"를 참고하기 바랍니다.)

5. 객체의 생성과 접근

리스트2에서 객체를 생성하고 접근하는 문장을 주석에 따라 차근차근 살펴보기 바랍니다.

리스트 2 : instance01.php

<?php

 

// Monitor 클래스가 정의된 화일을 포함시킨다.

include("./class.Monitor1.php");

 

// 인스턴스 두 개를 생성한다.

$mon1 = new Monitor1;

$mon2 = new MoNiToR1;

 

 

// 인스턴스 변수에 접근하는 방법

$mon1->vendor = "LG";

$mon1->modelName = "HiSync 15VN";

$mon1->screenSize = "15inch";

 

$mon2->vendor = "Samsung";

$mon2->modelName = "SyncMaster 3";

$mon2->screenSize = "14inch";

 

 

// 인스턴스 메소드를 호출하는 방법

$mon1->PowerOn();

$mon2->PowerOff();

 

 

print "제조사 : " . $mon1->vendor . "\n";

print "모델이름 : " . $mon1->modelName . "\n";

print "화면크기 : " . $mon1->screenSize . "\n";

print "전원상태 : " . $mon1->powerState . "\n";

 

print "제조사 : " . $mon2->vendor . "\n";

print "모델이름 : " . $mon2->modelName . "\n";

print "화면크기 : " . $mon2->screenSize . "\n";

print "전원상태 : " . $mon2->powerState . "\n";

 

?>

 

우선 새로운 객체를 생성하기 위해서는 키워드 new다음에 다음과 같이 클래스이름을 부여하는 형식이면 됩니다.

$[객체이름] = new [클래스 이름];

객체 역시 변수의 일종이므로 [객체이름]은 대소문자를 구분해 사용하지만, [클래스이름]은 좀다릅니다. 함수의 이름 처럼 PHP는 [클래스 이름]의 대소문자를 전혀 구분하지 않습니다. 따라서 '$mon2'라는 객체를 생성하는 것에 문법적인 에러가 발생하지는 않겠지만, 가급적 클래스를 정의할 때의 이름대로 사용하는 것이 코드의 재사용성을 높일 수 있는 방법입니다. (내부적으로 PHP는 함수 이름이나 클래스 이름은 모두 소문자로 처리하는 것 같습니다.)

인스턴스 변수나 메쏘드를 접근하는 문법은 다음과 같습니다.

$[객체이름]->[인스턴스변수의이름];
$[객체이름]->[메쏘드의이름](매개변수들);

인스턴수 변수도 변수의 일종이므로 대소문자를 구분한 다는 것에 비해 메쏘드는 함수의 일종이므로 대소문자를 구분하지 않는다는 것을 추측할 수 있겠지요... 그런데, 리스트2를 보면 인스터스 변수에 값을 설정하는 것이 좀 번거러워 보이지 않나요. 사실 리스트1이나 리스트2처럼 사용할 바에는 차라리 배열을 사용하는 것이 오히려 더 나은 방법으로 보입니다. 그럼 우선 Monitor1클래스의 인스턴수 변수를 초기화하는 좀더 나은 방법인 생성자에 대해 알아 보기로 하겠습니다.

6. 생성자 정의와 사용

리스트1의 클래스 정의 안에 다음과 같은 메쏘드를 추가시켜 보겠습니다.

  function Monitor1($vendor = "", $modelName = "", $screenSize = "")

  {

    $this->vendor = $vendor;

    $this->modelName = $modelName;

    $this->screenSize = $screenSize;

    $this->PowerOff();

  }

이렇게 하면 리스트2의 객체를 생성하고 인스턴스 변수에 값을 할당하는 긴 문장을 다음과 같이 두문장으로 해결할 수 있습니다.

$mon1 = new Monitor2("LG", "HiSync 15VN", "15inch");

$mon2 = new MoNiToR2("Samsung", "SyncMaster 3", "14inch");

정말 간단하지요... 이렇게 클래스의 이름과 같은 이름을 가진 메쏘드를 생성자(Constructor)라고 부르며, 생성자는  객체가 제일 처음 만들어질 때 자동적으로 호출돼 실행됩니다. 그리고 '$this->'뒤에는 인스턴스 변수 뿐 아니라 인스턴스 메쏘드도 올 수 있다는 것 역시 눈여겨 보기 바랍니다.

 

7. 추상화에 대해

추가한 생성자를 통해 실제 코딩의 양을 줄일 수 있었다. 리스트2에서 매번 인스턴스 변수를 출력할 때 마다 새로 입력한다는 것은 정말 불편한 작업이란 걸 알 수 있을 것입니다. 그래서 출력 부분을 PrintOut()이라는 메쏘드로 만들면 어떻게 될까요. 잘 생각해 보면 앞의 생성자도 조금 문제가 있습니다. 만약 중간에 값이 변할 경우를 생각해 보기 바랍니다.

이런 경우를 고려해 Monitor1클래스를 수정한 Monitor2 클래스가 바로 리스트 3입니다.

리스트 3 : class.Monitor2.php

<?php

// filename : class.Monitor2.php

 

define("ON", "On");

define("OFF", "Off");

 

class Monitor2 {

 

  var $vendor;

  var $modelName;

  var $screenSize;

 

  var $powerState;

 

  // 생성자

  function Monitor2($vendor = "", $modelName = "", $screenSize = "")

  {

    $this->setValue($vendor, $modelName, $screenSize);

    $this->PowerOff();

  }

 

  // 인스턴스가 생성된 다음에 인스턴스 변수를 수정하고 싶을 때 호출한다.

  function setValue($vendor, $modelName, $screenSize)

  {

    $this->vendor = $vendor;

    $this->modelName = $modelName;

    $this->screenSize = $screenSize;

  }

 

  function PowerOn() {

    $this->powerState = ON;

  }

  

  function PowerOff() {

    $this->powerState = OFF;

  }

 

  // 파워가 켜져 있는지 꺼져 있는지를 검사한다.

  function IsOn() {

    if (OFF == $this->powerState)

      return false;

    else

      return true;

  }

 

  // 요구 형식에 맞춰 현재 객체 상태를 출력한다.

  function PrintOut() {

    print "제조사 : " . $this->vendor . "\n";

    print "모델이름 : " . $this->modelName . "\n";

    print "화면크기 : " . $this->screenSize . "\n";

    print "전원상태 : " . $this->powerState . "\n";

  }

}

?>

리스트 3에서 만약 IsOn()같은 메쏘드가 없다면 모니터 파워가 켜져 있는지 아닌지 어떻게 알 수 있을 까요. 물론 Monitor2의 인스턴스 변수 '$powerState'를 직접 접근해 다음과 같은 방법으로 알 수도 있습니다.

if("ON" == $mon1->powerState) {

    // 파워가 켜져 있을 경우

}else {

    // 파워가 꺼져 있는 경우

}

그렇지만 이럴 경우 'powerState'가 켜져 있는 상태일 때 값('ON')과 꺼져 있는 상태일 때 갖는 값('OFF')까지 알아야 하는데, 이런 식으로 클래스를 설계하는 것은 좋은 방법이 아닙니다.  클래스를 사용하는 사라의 입장에서는 (클래스가 내부적으로 어떻게 돌아가는지에 대해 잘 몰라도 프로그래밍할 수 있도록 하는 것을 정보의 은닉, 혹은 캡슐화 등의 용어라 부릅니다.) 이렇게 하면 powerState란 인스턴스 변수에 대해 전혀 모르고도 모니터의 상태를 체크할 수 있게 됩니다.

if($mon1->IsOn()) {

    // 파워가 켜져 있을 경우

}else {

    // 파워가 꺼져 있는 경우

}

그럼 리스트2와 같은 일을 하는 리스트 4를 비교해 보겠습니다.

<?php

// filename : instance02.php

 

include("./class.Monitor2.php");

 

$mon1 = new Monitor2("LG", "HiSync 15VN", "15inch");

$mon2 = new MoNiToR2("Samsung", "SyncMaster 3", "14inch");

 

$mon1->PowerOn();

$mon2->PowerOff();

 

$mon1->PrintOut();

$mon2->PrintOut();

 

?>

 

Monitor2

+Vendor
+modelName
+screenSize
-Powerstate

+Monitor2()
+setValue()
+Poweron()
+Poweroff()
+IsOn()
+PrintOut()

클래스의 정의 부분과 관련된 소스코드는 많이 늘어났지만, 그에 비해 객체가 작동하는 코드는 매우 짧아졌습니다. 이렇게 클래스만 잘 정의해 놓으면 아주복잡한 일도 몇줄의 코드로 간단하게 해결할 수 있습니다. 그런데, 이런 장점은 함수를 사용해 프로그래밍할 때도 비숫하게 발휘됩니다. 결코 객체지향 프로그래밍의 장점만은 아닌 셈이죠. 사실 객체지향 프로그래밍의 더 큰 장점은 클래스를 상속받아 새로운 클래스로 손쉽게 확장할 수 있다는 것입니다.

 

8. 클래스의 상속

앞에서 모니터의 속성과 행동을 정의한 클래스를 만들었는데, 이 모니터 클래스는 TV의 모니터나 컴퓨터의 모니터와 같이 여러 모니터로 파생될 수 있습니다.

 

이렇게 이미 정의된 클래스의 속성(인스턴스 변수)과 행동 (메쏘드)을 그대로 물려받아 새롭게 확장된 클래스를 만드는 것을 상속이라고 말하며, 기존의 클래스에서 얼마든지 새로운 클래스를 만들 수 있기 때문에 쉽게 재사용할 수 있습니다. 물론 기존의 클래스를 사용한 코드는 전혀 고칠 필요가 없습니다. 새롭게 확장된 클래스에 맞춘 코드만 작성하면 되죠. 어쨌든 실제 PHP에서 클래스를 상속하기 위해서는 다음과 같은 문법을 사용하면 됩니다.

class [자식 클래스] extends [부모 클래스] {
   //추가할 속성을 인스턴스 변수로 정의한다.
    // 추가할 행동을 메쏘드로 정의한다.
}

여기서 자식 클래스를 서브 클래스라고 부르고,  extends뒤에 나오는 부모 클래스를 슈퍼 클래스라고도 부릅니다. 당연하겠지만, 자식 클래스가 새롭게 확장된 클래스를 나타내고 부모 클래스는 기존에 정리된 클래스를 말하는 것이겠지요. 그런데 PHP는 자바처럼 하나의 부모 클래스만 상속 하는 단일 상속만을 허용한다는 점, 기억해두세요.. 그럼 앞의 문법을 바로 적용하기 전에 TV클래스에서 새롭게 확장될 속성과 행동을 생각해 봅시다.

TV에는 여러 속성과 행동이 있겠지만, 가장 기본적인 속성과 행동을 생각해 봅시다. 앞에서 미리 말했지만, TV는 모니터의 속성과 행동을 모두 갖고 있습니다. 거기에 볼륨과 채널 정도의 속성을 추가하면 되겠지요... 따라서 TV에서는 볼륨을 높이고(VolumeUp) 낮추는(VolumeDown) 행동과 채널을 바꾸는 행동(ChannelUp, ChannelDown)을 할 수 있습니다. 그외에 현재의 볼륨 정도가 얼마인지(getVolume),현재 채널이 몇변인지(getChannel) 알 수 있어야겠지요.

TV

+volume;
+channel;

+Monitor()
+VolumeUp()
+VolumeDown()
+ChannelUp()
+ChannelDown()
+getVolume()
+getChannel()
+PrintOut()

 

 TV 클래스를 구현한 리스트 5를 보면 여기에서 정의한 TV 클래스는 Monitor클래스를 상속하고 있으며, Monitor클래스는 Monitor2와 동일한 클래스입니다. (클래스 이름과 생성자 이름 만 다르게 하면 되겠지요). 이미 어떤식으로 정의할 지 속성과 행동을 설명했으므로 리스트5를 이해하는 것이 어렵지 않을 겁니다.

리스트5 : class.TV.php

<?php

// filename : class.TV.php

 

include("./class.Monitor.php");

 

// 볼륨과 채널의 한계값들

define("MIN_VOLUME", 0);

define("MAX_VOLUME", 1000);

define("MIN_CHANNEL", 1);

define("MAX_CHANNEL", 200);

 

class TV extends Monitor {

  

  // 추가되는 속성들

  var $volume;

  var $channel;

 

  // TV의 생성자

  function TV($vendor = "", $modelName = "", $screenSize = "")

  {

    // Monitor의 생성자를 호출

    $this->Monitor($vendor, $modelName, $screenSize);

    

    $this->volume = 200;

    $this->channel = 11;

  }

 

  // 추가되는 메소드들

  

  function VolumeUp() {

    $this->volume = $this->volume + 10;

 

    // 볼륨이 정해놓은 것 이상 올라갈 수 없게 한다.

    if (MAX_VOLUME <= $this->volume) {

      $this->volume = MAX_VOLUME;

    }

  }

 

  function VolumeDown() {

    $this->volume = $this->volume - 10;

 

    // 볼륨이 정해놓은 것 이상 내려갈 수 없게 한다.

    if (MIN_VOLUME >= $this->volume) {

      $this->volume = MIN_VOLUME;

    }

  }

 

  function ChannelUp() {

    $this->channel++;

    

    // 채널을 정해놓은 것 이상 올라갈 수 없게 한다.

    if (MAX_CHANNEL <= $this->channel) {

      $this->channel = MAX_CHANNEL;

    }

  }

  

  function ChannelDown() {

    $this->channel--;

 

    // 채널을 정해놓은 것 이상 내려갈 수 없게 한다.

    if (MIN_CHANNEL >= $this->channel) {

      $this->channel = MIN_CHANNEL;

    }

  }

 

  function getVolume() { return $this->volume; }

  function getChannel() { return $this->channel; }

 

  // Monitor의 PrintOut()를 오버라이딩한다.

  function PrintOut() {

    print "제조사 : " . $this->vendor . "\n";

    print "모델이름 : " . $this->modelName . "\n";

    print "화면크기 : " . $this->screenSize . "\n";

    print "전원상태 : " . $this->powerState . "\n";

    print "현재볼륨 : " . $this->getVolume() . "\n";

    print "현재채널 : " . $this->getChannel() . "\n";

  }

}

?>

 

단지 부모 클래스의 생성자를 명시적으로 호출해야 한다는 것을 잊지 말기 바랍니다. 상황에 따라 필요 없는 경우도 있습니다. 리스트 5의 'PrintOut()'과 같이 부모 클래스에 있는 메쏘드를 자식 클래스에서 다르게 변형해 재정의하는 것을 오버라이딩(Overriding)한다고 합니다.  오버로딩이나 오버라이딩에 관한 내용은 생략합니다. 여기까지 잘 정리하기 바랍니다.

 

9. 리모콘 클래스 구현해보기

이번에는 Monitor클래스를 상속한 TV 클래스의 객체를 원격으로 제어할 수 있는 Romocon이라는 클래스를 구현해 보는 것입니다. 어떤식으로 구현할 지 감이 안 잡히는 사람을 위해 힌트를 드릴게요.

우선 Remocon은 TV와는 전혀 별개의 객체라는 것입니다. 상속관계는 분명 아니고 Remocon이 TV에 속하지도 않습니다. 하지만, Remocon이 어떤 행동을 하면 적외선으로 연결돼 TV는 Remocon이 지시하는 대로 행동하게 됩니다. 하지만, 그 반대로 TV의 채널을 변화시킨다고 Remocon의 속성이 변하지는 않습니다. TV의 객체는 Remocon의 객체를 몰라도 되지만, Remocon의 객체는 반드시 TV의 객체를 구분해야 한다는 점만 잘 생각하기 바랍니다. 그리고 Remocon에서 채널 숫자를 누를 때 역시 채널이 변한다는 것을 알고 있겠지요. 이것도 가능한 Remocon 클래스를 구현해 보기 바랍니다. 단, 이때 TV클래스를 고쳐서는 안되고, Remocon클래스 안에서 구현해 보기 바랍니다.

리스트 6 : class.Remocon.php

<?php

// filename : class.Remocon.php

 

// include()와 include_once()의 차이는 무엇일까요?

include_once("./class.TV.php");

 

class Remocon {

  // 주위에 있는 TV를 가리키는 인스턴스 변수

  var $assignedTV;

 

  // Remocon의 생성자

  function Remocon($tv = "") {

    if (false == empty($tv)) {

      $this->Connect($tv);

    }

    else {

      $this->assignedTV = false;

    }

  }

 

  // Remocon을 TV로 가리키는 메소드이며

  // &$tv대신 $tv를 사용해보고 제대로 결과가 나오는지 확인해 보세요.

 

  function Assign(&$tv) {

    // $tv가 TV 클래스의 인스턴스인지 확인

    if ((true == is_object($tv)) && ("tv" == get_class($tv))) {

      $this->assignedTV = &$tv;

    }

 

    // $tv가 TV 클래스가 아닌 경우

    else {

      die("인스턴스가 Object형이 아니거나, TV 클래스가 아닙니다.\n");

    }

  }

 

  // Remocon이 TV를 가리키고 있는지 체크

  function IsAssigned() {

    if (false == $this->assignedTV) {

      return false;

    }

    else {

      return true;

    }

  }

 

  function PowerOn() {

    if ($this->IsAssigned()) {

      // 인스턴스 변수로 오브젝트형이 지정되어 있을 경우

      // 연달아 호출하는 방식으로 사용하면 된다.

      $this->assignedTV->VolumeUp();

    }

    else {

      die("주위에 TV가 없습니다.\n");

    }

  }

 

  function PowerOn() {

    if ($this->IsAssigned()) {

      // 인스턴스 변수로 오브젝트형이 지정되어 있을 경우

      // 연달아 호출하는 방식으로 사용하면 된다.

      $this->assignedTV->VolumeUp();

    }

    else {

      die("주위에 TV가 없습니다.\n");

    }

  }

 

  function VolumeUp() {

    if ($this->IsAssigned()) {

      $this->assignedTV->VolumeUp();

    }

    else {

      die("주위에 TV가 없습니다.\n");

    }

  }

 

  function VolumeDown() {

    if ($this->IsAssigned()) {

      $this->assignedTV->VolumeDown();

    }

    else {

      die("주위에 TV가 없습니다.\n");

    }

  }

 

  function ChannelUp() {

    if ($this->IsAssigned()) {

      $this->assignedTV->ChannelUp();

    }

    else {

      die("주위에 TV가 없습니다.\n");

    }

  }

  

  function ChannelDown() {

    if ($this->IsAssigned()) {

      $this->assignedTV->ChannelDown();

    }

    else {

      die("주위에 TV가 없습니다.\n");

    }

  }

  

  function setChannel($channel) {

    // 지정된 채널이 설정할 수 있는 채널 범위에 없을 경우

    if ((MIN_CHANNEL > $channel) && (MAX_CHANNEL < $channel)) {

 

      // 아무것도 하지 않는다.

      return;

    }

 

    // 지정된 채널이 현재 채널보다 높은 경우

    if ($this->assignedTV->getChannel() < $channel) {

 

      // 같아질 때까지 계속 채널을 증가시킨다.

      while ($this->assignedTV->getChannel() != $channel) {

        $this->ChannelUp();

      }

    }

 

    // 지정된 채널이 현재 채널보다 낮은 경우

    else if ($this->assignedTV->getChannel() > $channel) {

 

      // 같아질 때까지 계속 채널을 감소시킨다.

      while ($this->assignedTV->getChannel() != $channel) {

        $this->ChannelDown();

      }

    }

 

    // 지정된 채널이 현재 채널하고 같은 경우

    else {

      // 아무것도 하지 않는다.

      return;

    }

  }

}

?>

 

리스트 7 : remoconAndTV.php

<?php

// filename : class.Remocon.php

 

// include()와 include_once()의 차이는 무엇일까요?

include_once("./class.TV.php");

 

class Remocon {

  // 주위에 있는 TV를 가리키는 인스턴스 변수

  var $assignedTV;

 

  // Remocon의 생성자

  function Remocon($tv = "") {

    if (false == empty($tv)) {

      $this->Connect($tv);

    }

    else {

      $this->assignedTV = false;

    }

  }

 

  // Remocon을 TV로 가리키는 메소드이며

  // &$tv대신 $tv를 사용해보고 제대로 결과가 나오는지 확인해 보세요.

 

  function Assign(&$tv) {

    // $tv가 TV 클래스의 인스턴스인지 확인

    if ((true == is_object($tv)) && ("tv" == get_class($tv))) {

      $this->assignedTV = &$tv;

    }

 

    // $tv가 TV 클래스가 아닌 경우

    else {

      die("인스턴스가 Object형이 아니거나, TV 클래스가 아닙니다.\n");

    }

  }

 

  // Remocon이 TV를 가리키고 있는지 체크

  function IsAssigned() {

    if (false == $this->assignedTV) {

      return false;

    }

    else {

      return true;

    }

  }

 

  function PowerOn() {

    if ($this->IsAssigned()) {

      // 인스턴스 변수로 오브젝트형이 지정되어 있을 경우

      // 연달아 호출하는 방식으로 사용하면 된다.

      $this->assignedTV->VolumeUp();

    }

    else {

      die("주위에 TV가 없습니다.\n");

    }

  }

 

  function PowerOn() {

    if ($this->IsAssigned()) {

      // 인스턴스 변수로 오브젝트형이 지정되어 있을 경우

      // 연달아 호출하는 방식으로 사용하면 된다.

      $this->assignedTV->VolumeUp();

    }

    else {

      die("주위에 TV가 없습니다.\n");

    }

  }

 

  function VolumeUp() {

    if ($this->IsAssigned()) {

      $this->assignedTV->VolumeUp();

    }

    else {

      die("주위에 TV가 없습니다.\n");

    }

  }

 

  function VolumeDown() {

    if ($this->IsAssigned()) {

      $this->assignedTV->VolumeDown();

    }

    else {

      die("주위에 TV가 없습니다.\n");

    }

  }

 

  function ChannelUp() {

    if ($this->IsAssigned()) {

      $this->assignedTV->ChannelUp();

    }

    else {

      die("주위에 TV가 없습니다.\n");

    }

  }

  

  function ChannelDown() {

    if ($this->IsAssigned()) {

      $this->assignedTV->ChannelDown();

    }

    else {

      die("주위에 TV가 없습니다.\n");

    }

  }

  

  function setChannel($channel) {

    // 지정된 채널이 설정할 수 있는 채널 범위에 없을 경우

    if ((MIN_CHANNEL > $channel) && (MAX_CHANNEL < $channel)) {

 

      // 아무것도 하지 않는다.

      return;

    }

 

    // 지정된 채널이 현재 채널보다 높은 경우

    if ($this->assignedTV->getChannel() < $channel) {

 

      // 같아질 때까지 계속 채널을 증가시킨다.

      while ($this->assignedTV->getChannel() != $channel) {

        $this->ChannelUp();

      }

    }

 

    // 지정된 채널이 현재 채널보다 낮은 경우

    else if ($this->assignedTV->getChannel() > $channel) {

 

      // 같아질 때까지 계속 채널을 감소시킨다.

      while ($this->assignedTV->getChannel() != $channel) {

        $this->ChannelDown();

      }

    }

 

    // 지정된 채널이 현재 채널하고 같은 경우

    else {

      // 아무것도 하지 않는다.

      return;

    }

  }

}

?>

 

 

[목차]

개인정보취급방침 서비스이용약관 모바일 버전으로 보기 상단으로

TEL. 063-469-4551 FAX. 063-469-4560 전북 군산시 대학로 558
군산대학교 컴퓨터정보공학과

Copyright © www.leelab.co.kr. All rights reserved.