PHP & MySQL 게시판/PHP

PHP 객체지향 프로그래밍( 클래스 / 객체 / 속성 / 메서드 / 생성자 / 소멸자 / 접근 제어자 / Setter/Getter )

Dokker 2023. 11. 7. 15:46

객체지향 프로그래밍(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를 이용하여 안전하게 속성의 값을 관리 할 수 있다.