객체지향 프로그래밍(Object-Oriented Programming)
객체지향 프로그래밍(Object-Oriented Programming)은 객체를 중심으로 프로그램이 진행되는 데 이 기법을 이용하면 프로그램을 훨씬 간경하고 구조적으로 작성할 수 있다.
객체지향에서 사용되는 클래스, 객체, 속성, 메소드의 개념을 파악하여 객체지향 프로그램을 작성
클래스와 객체
객체지향 프로그래밍(Object-Oriented Programming)은 객체(Object)를 중신으로 프로그래밍이 진행된다. 클래스(Class)는 객체를 생성하는 일종의 틀이다. 객체지향 프로그래밍과 반대되는 개념이 절차적 프로그래밍(Procedural Programming)이다.
절차적 프로그래밍은 기본적으로 프로그램의 진행이 절차적, 즉 순차적으로 이루어진다.
프로그램이 진행되다가 함수가 호출되면 정의된 함수를 실행하고 다시 그 위치로 복귀하여 다시 순차적으로 프로그램이 진행된다. 지금까지 실습한 모든 예제들에서 사용된 방식이 절차적 프로그래밍이다.
절차적 프로그래밍과는 다소 다른 개념인 객체 지향 프로그래밍에서는 프로그램의구성이 객체를 중심으로 이루어진다. 이 객체는 속성(Property)과 메소드(method)로 구성된다.
객체지향 프로그래밍은 절차적 프로그래밍에 비해 다음과 같은 장점이 있다.
프로그램 실행이 빠르다.
프로그램 구조가 명확해서 유지보수가 쉽다.
코드가 간결해지고 개발 기간이 단축된다.
클래스와 객체의 사용 예
<?php
class Person {
public $name ;
public $age ;
public function intro () {
echo "이름 : " . $this -> name . ", 나이 : " . $this -> age ;
}
}
// 객체 생성
$hong = new Person ();
$hong -> name = "홍길동" ;
$hong -> age = 20 ;
$hong -> intro ();
? >
person 클래스를 정의한다. 이 클래스는 $name 과 $age 속성과 intro() 메소드로 구성된다.
02~08 $name 속성과 $age 속성을 정의한다. 여기서 public은 속성의 형을 나타낸다.
03,04 public 형은 해당 속성을객체 내부와 외부에서 모두 사용할 수 있게 한다.
05~07 intro() 메소드는클래스의 속성 $nmae 과 $age를 화면에 출력하는 역할을 한다.
여기서 $this는 클래스 내부의 속성에 접근하기 위한 키워드로써 클래스(또는 객체) 자기 자신을 가리킨다.
$this->name은 캘래스 자신의 속성인 $name 값을 의미한다. 같은 맥락에서
$this->age는 클래스내부의 $age 속성 값을 나타낸다.
11 Person 클래스로부터 새로운 객체 $hong을 생성한다.
13 $hone->name은 $hong 객체의 $name 속성을 의미한다. 13행은 $hong 객체의 $name 속성에 '홍길동'을 저장한다.
14 $hone의 $age 속성에 20을 저장한다.
16 $hong->intro()는 5행의 intro() 메소드를 호출한다. 6행에 의해 그림 7-2에 나타난 것과 같이 $hong 객체의 이름과 나이가 출력된다.
<?php
class Person { //-------------------------------------------------------
public $name ; //--------------------------------------> 속성 |
public $age ; // -------------------------------------> 속성 |
public function intro () { //----------------------------| | ===> 클래스 정의
echo "이름 : " . $this -> name . ", 나이 : " . $this -> age ; // 메소드 |
} //------------------------------------------------------| |
} // |
// 객체 생성
$hong = new Person (); //---------> 객체 생성
$hong -> name = "홍길동" ;
$hong -> age = 20 ;
$hong -> intro ();
? >
속성과 메소드
객체 지향 프로그래밍에서는 제일 먼저 클래스의 속성과 메소드를 정의하여야 한다.
객체지향 방식으로 사각형의 둘레 길이와 넓이를 구한다.
<?php
class Rectangle {
public $width ;
public $height ;
public function getLength () {
return ( $this -> width * 2 + $this -> height * 2 );
}
public function getArea () {
return ( $this -> width * $this -> height );
}
}
$rect1 = new Rectangle ();
$rect1 -> width = 20 ;
$rect1 -> height = 10 ;
echo "너비 : " . $rect1 -> width . "<br>" ;
echo "높이 : " . $rect1 -> height . "<br>" ;
echo "사각형 둘레 길이 : " . $rect1 -> getLength () . "<br>" ;
echo "사각형 넓이 : " . $rect1 -> getArea ();
? >
<?php
class Rectangle { // 클래스 Rectangle 을 정의
public $width ; // 속성
public $height ; // 속성
public function getLength () { // 메소드
return ( $this -> width * 2 + $this -> height * 2 );
}
public function getArea () { // 메소드
return ( $this -> width * $this -> height );
}
}
$rect1 = new Rectangle (); // Rectnagle 클래스로부터 새로운 객체 rect1을 생성
$rect1 -> width = 20 ;
$rect1 -> height = 10 ;
echo "너비 : " . $rect1 -> width . "<br>" ; //출력
echo "높이 : " . $rect1 -> height . "<br>" ; // 출력
echo "사각형 둘레 길이 : " . $rect1 -> getLength () . "<br>" ; // 5~7행에서정의된 getlength() 메소드를 호출
echo "사각형 넓이 : " . $rect1 -> getArea (); // 8~10행에서 정의된 getArea() 메소드를 호출
? >
생성자와 소멸자
객체를 생성할 때 자동으로 실행되는 메소드를 생성자(Constructor)라고 하고, 반대로 객체가 소멸 될 때 자동으로 실행되는 메소드를 소멸자(Destructor)라고 한다. 일반적으로 객체는 해당 프로그램이 종료 될 때 소멸 된다.
생성자
객체 생성 시 속성 값을 설정하는데 사용 된다.
<?php
class Triangle {
public $width ;
public $height ;
public function __construct ( $width , $height ) {
$this -> width = $width ;
$this -> height = $height ;
}
public function getArea () {
$area = $this -> width * $this -> height * 0.5 ;
return $area ;
}
}
$tri1 = new Triangle ( 10 , 5 );
echo "삼각형의 넓이 : " . $tri1 -> getArea ();
? >
<?php
class Triangle { // 클래스 Triangle 생성
public $width ; // 속성
public $height ; // 속성
public function __construct ( $width , $height ) { // 생성자 함수 __construct = Triangle 클래스에 인수가 존재하면 생성자 함수가 실행
$this -> width = $width ; // 속성 정의
$this -> height = $height ; // 속성 정의
}
public function getArea () { // 메서드
$area = $this -> width * $this -> height * 0.5 ; // 삼각형 넓이 공식 = $area
return $area ; // 결과값 호출
}
}
$tri1 = new Triangle ( 10 , 5 ); // Triangle 클래스로부터 $tri1 새로운 객체 생성
echo "삼각형의 넓이 : " . $tri1 -> getArea (); // 9~12행에 정의된 getArea() 메서드 호출
? >
소멸자
객체가 소멸 될 때 실행된다.
<?php
class Person {
public $name ;
public function __construct ( $name ) {
$this -> name = $name ;
}
public function __destruct () {
echo "이름은 " . $this -> name . "입니다." ;
}
}
$person1 = new Person ( "홍길동" );
? >
8~10 소멸자 함수 __destruct()는 13행에서 생성된 객체가 소멸, 즉 프로그램이 종료 될 때 실행된다. 따라서 프로그램이 종료되면 소면자 __destruct() 함수 내에 있는 9행의 echo문에 의해 '이름은 홍길동입니다.'가 출력된다.
클래스의 상속
클래스는 extends 키워드를 이용하여 다른 클래스로부터 속성과 메소드를 상속받을 수 있다. 이러한 클래스의 상속(Inheritance) 기능으로 인하여 객체지향 프로그래밍의 장점이 더욱 부각될 수 있다.
클래스 상속의 예
<?php
class Rectangle {
public $width ;
public $height ;
public function __construct ( $width , $height ) {
$this -> width = $width ;
$this -> height = $height ;
}
public function getArea () {
return ( $this -> width * $this -> height );
}
}
class Square extends Rectangle {
public function isSquare () {
if ( $this -> width == $this -> height ) {
return true ; // 정사각형인 경우
}
else {
return false ; // 직사각형이 아닌 경우
}
}
}
$rect = new Square ( 10 , 10 );
if ( $rect -> isSquare ())
echo "정사각형의 넓이 : " ;
else
echo "직사각형의 넓이 : " ;
echo $rect -> getArea ();
? >
<?php
class Rectangle { // Rectangle 클래스는 2개의 속성과 생성자 1개의 메서드로 구성
public $width ;
public $height ;
public function __construct ( $width , $height ) {
$this -> width = $width ;
$this -> height = $height ;
}
public function getArea () {
return ( $this -> width * $this -> height );
}
}
class Square extends Rectangle { // Square 클래스는 2-12행에서 정의한 Rectangle 클래스의 모든 자산, 속성, 생성자, 메서드를 상속 받는다.
public function isSquare () { // Square 클래스는 상속받는 자신에 추가적으로 isSquare() 메소드를 가진다.
if ( $this -> width == $this -> height ) { //너비 == 높이가 같을 경우 정사각형이다 ---> 참
return true ; // 정사각형인 경우 결과값은 True 값을 반환
}
else {
return false ; // 정사각형이 아닌 경우 False 값을 반환
}
}
}
$rect = new Square ( 10 , 10 ); // $rect 객체 생성 이때 5-8행 생성자 함수가사용된다.
if ( $rect -> isSquare ()) // $rect 가 isSquare 메서드를 호출하였을때 반환되는 값이 True이면
echo "정사각형의 넓이 : " ; // 정사각형의 넓이 : 출력
else
echo "직사각형의 넓이 : " ; // 조건문이 False일때 --> 직사각형의 넓이 : 출력
echo $rect -> getArea (); // 9-11행의 getArea() 출력
? >
접근 제어자
객체지향 프로그래밍에서 클래스를 정의하다 보면 속성과 메소드의 접근을 제한할 필요가 있따. 이때 사용하는 것이 다음의 세 가지 접근 제어자(Access Modifier)이다.
- public ---> 속성과 메소드가 어느 곳에서든 다 접근 가능하다.
- protected --> 속성과 메소드가 해당 클래스와 그 클래스를 상속받은 클래스 내에서만 접근 가능하다.
- private ---> 속성과 메소드가 해당 클래스 내에서만 접근 가능하다.
public 접근 제어자의 사용
<?php
class Member {
public $name ;
public function getName () {
return $this -> name ;
}
}
$mem = new Member ();
$mem -> name = "홍길동" ; // 외부에서도 접근 가능
echo "이름 : " . $mem -> getName ();
? >
<?php
class Member { // Member 클래스를 정의
public $name ; // 접근제어자 public의 사용 $name 속성 정의
public function getName () { // getName 메소드 정의
return $this -> name ; // 리턴값으로 $name 속성값을 사용
}
}
$mem = new Member (); // 객체 생성 위에서 public으로 선언하였기 때문에 mem객체의 $name 속성
$mem -> name = "홍길동" ; // 외부에서도 접근 가능 / $mem->name 저장가능
echo "이름 : " . $mem -> getName (); // 이름 : 홍길동 출력
? >
private 접근 제어자의 사용
<?php
class Member {
private $name ;
public function getName () {
return $this -> name ;
}
}
$mem = new Member ();
$mem -> name = "홍길동" ; // 접근 오류 발생
echo "이름 : " . $mem -> getName ();
? >
3행에서 $name 속성에 Private 접근 제어자가 사용되었기 때문에 12행에서와 같이 클래스 외부인 객체에서는 $name 속성에 접근할 수 없게 된다.
이와 같이 private접근 제어자로 선언된 속성과 메소드는 클래스 내부에서만 사용가능하고 외부에서는 접근할 수 없다.
private 접근 제어자로 선언된 속성에 값을 저장하기 위해서는 Setter(세터)를 사용하여야 한다. Setter는 객체의 메소드에서 속성값을 저장하는 데 사용되는 메소드를 말한다. 반대로 값을 가져오는 데 사용되는 메소드를 Getter(게터)라고 한다.
Private 속성에 사용되는 Setter와 Getter의 사용법
<?php
class Member {
private $name ;
public function setName ( $name ) {
$this -> name = $name ;
}
public function getName () {
return $this -> name ;
}
}
$mem = new Member ();
$mem -> setName ( "김정호" );
echo "이름 : " . $mem -> getName ();
? >
<?php
class Member { // 클래스 Member 정의
private $name ; // 접근 제어자 private $name 속성
public function setName ( $name ) { // 속성 $name에 값을 저장하기 위해 Setter 사용
$this -> name = $name ;
}
public function getName () { // 속성 $name에 값을 가져오기 위해 Getter 사용
return $this -> name ; // $name을 리턴한다.
}
}
$mem = new Member (); // 클래스 Member로 부터 객체 $mem 생성
$mem -> setName ( "김정호" ); // Setter사용 $mem에 '김정호'를 저장
echo "이름 : " . $mem -> getName (); // 이름 : '김정호'를 불러오기위해 Getter 사용
? >
그러나 클래스의 속성 값이 외부에서 변경되면 곤란한 경우도 있다. 이럴 경우에는 클래스의 속성을 Private로 선언한 다음 Setter/Getter를 이용하여 안전하게 속성의 값을 관리 할 수 있다.