Language/PHP

공부 내용 정리 PHP :: 초급 III

Cs.Woo 2021. 6. 1. 03:00

# 클래스와 인스턴스 그리고 메소드 생성

 이전 장에서 학습한 객체라는 것을 만들 수 있는 틀(frame)과 같은 클래스, 그리고 클래스를 통하여 변수 안에 저장되는 인스턴스 그리고, 클래스 안에 정리되는 메소드에 대한 학습을 하였고, 본 장에서는 그것을 정리하였다.

 

# 클래스 생성

 클래스를 생성하는 방법은 하기의 예제2와 같고, 클래스에 넣고자 하는 내용은 예제1과 같다.

 

<?php
## 스토리

# 1. 함수를 통하여 파일을 제어
var_dump(is_file('data.txt');
var_dump(is_dir('data.txt');
var_dump(file_get_contents('data.txt'));
file_put_contents('data.txt', rand(1,100));


# 1. 객체로서 파일을 제어
$file = new SplFileObject('data.txt');
var_dump($file->isFile());
var_dump($file->isDir());
var_dump($file->fread($file->getSize()));
$file -> fwrtie(rand(1,100));

$file2 = new SplFileObject('data2.txt');
var_dump($file2->isFile());
var_dump($file2->isDir());
var_dump($file2->fread($file->getSize()));
$fil2e -> fwrtie(rand(1,100));

 

클래스를 만들고자 하는 내용은 상기와 같고, 만드는 방법은 하기와 같다.

 

<?php
# 클래스를 만드는 문법

class [클래스명] {
	function 메소드명() {
    	코드
        }
}

# 클래스를 사용하는 방법

$할당하고자 하는 변수명  = new [클래스명]();


#예제

class MyFileObject{
	
    function isFile() {
    return ture
    }
    
}

class YourFileObject{
	
    function isFile() {
    return ture
    }
    
}

$file = new MyFileObject();
var_dump($file->isFile()); #true


  메소드가 아닌 함수로서 기능을 사용하였거나, 선언하였다면, 그 함수는 해당 php파일 내에서는 동일 이름은 한 번만 사용이 가능하다. 즉 한 번 선언한 함수의 기능은 그 이름에 귀속되는것이다. 그러나 객체의 메소드로서 함수를 만들었다면, 객체의 이름이 다른 이상은 동일 메소드가 존재해도 상관이 없다.

 가령 상기의 예제처럼 MyFileObject안에 isFile()이라는 메소드가 있고, YourFileObject안에 isFile()이라는 메소드가 있어도 상관 없는것과 같은 이치이다.

  본래 함수만 사용했다면 isFile()이라는 함수는 단 한번만 정의 할 수 있는데, 상기의 객체 예제에서는 같은 이름으로 두번 정의 한 것을 확인할 수 있고, 정상적으로 작동되는 방법이다.

 

class MyFileObject{
	
    function isFile() {
    return is_file('data.txt');
    }
    
}

$file = new MyFileObject();
var_dump($file->isFile()); 


 

 # 인스턴스 변수 만들기

 본 장에서는 인스턴스마다 서로 다른 상태를 가지도록 하는 방법으로서의 인스턴스에 대하여 학습하였다.

 

 

<?php

class MyFileObject{
	function isFile(){
    	return is_File('data.txt');
        }
}

$file = new MyFileObject();
var_dump($file->isFile());

$file2 = new MyFileObject();
var_dump($file2->isFile());


# file1 과 file2가 서로 다른 값을 리턴할 수 있도록 조치를 취하기 위함

class MyFileObject{

	function isFile(){
    	return is_File($this->filename);
        }
        # 만일 그냥 $filename을 is_file의 인자로 준다면 에러가 발생한다.
        # 이유는 $filename은 isFile()이라는 함수 안에서만 존재하는 변수이기 때문이다.
        # 따라서 오류를 해결하기 위해서는 $this->filename 으로 작성해주어야 한다.
}


$file = new MyFileObject();
$file->filename = 'data.txt';
var_dump($file->isFile()); #true

$file2 = new MyFileObject();
$file2->filename = 'data2.txt';
var_dump($file2->isFile()); #false

 만일 data.txt 와 data2.txt의 존재 유무를 비교하고자 한다면, MyFileObject의 isFile메소드에 인자로서 data.txt와 data2.tx를 넣어서 참과 거짓을 비교해야할 것이다.

 일반적으로 함수를 사용하는 방식대로, MyFileObject의 객체 안에 isFile메소드 안에 return 옆 is_File()의 인자로서 $filename을 부여한다면, 에러가 발생한다. 그동안 함수를 사용한 방식대로 하면 논리적으로 오류가 있는 모양새인데, 이유는 다음과 같다.

 

 MyFileObject의 isFile메소드에서 $filename을 그냥 사용한다면, 그 메소드 안에서만 존재하는 지역변수로서 인식을 한다. isFile안에서는 $filename의 값을 따로 할당해주지 않았기 때문에 할당조자 되지 않은 존재하지 않는 변수명이 되기 때문에 실행을 할 수가 없게 되는 것이다.

 

 그렇다면, 객체에 전달되는 $filename을 인자로서 전달하고자 할 때는 어떻게 해야하는가? 상기의 예제와 같이 $this->filename 을 넣어주면 메소드의 밖에서 받은 값을 메소드의 인자로서 부여할 수 있게 된다.

 

 $this는 일종의 키워드이다. $this의 의미는 해당하는 클래스를 통해서 인스턴스화한 그 인스턴스 자체이다. 따라서, 상기 예제에서 $file에 클래스로서 객체를 생성하여 인스턴스가 생성되어 할당되었고, $file변수에 filename = 'data.txt'라는 식으로 filename이 할당되었으니, 인스턴스 자체에 할당된 filename을 사용하고자 한다면,

 $this(이 인스턴스의) -> filename(변수이름)의 값을 인자로 전달

이라는 의미로서 this를 사용해야 하는 것이다.

 같은 논리로서, 상기의 예제에서

$file = new MyFileObject();
$file->filename = 'data.txt';
var_dump($file->isFile()); #true
var_dump($file->filename); #data.txt

와 같이 file->filename을 한다면 file인스턴스 안에 전달된 filename이라는 변수의 값을 조회할 수 있게 된다. 

즉, file->filename = 'data.txt'; 은 파일의 값을 쓰는방식이고, file->filename 은 filename을 가져오는 방식이라고 이야기 할 수 있는 것이다.

 

상기 코드의 용어의 정리는 다음과 같다.

 

$file = new MyFileObject();
$file->filename = 'data.txt';
var_dump($file->isFile()); #true
var_dump($file->filename); #data.txt


// MyFileObject() : 클래스
// $file : 인스턴스

// isFile : 메소드
// filenmae이라는 변수 : 인스턴스 안에서만 유효하다. (인스턴스변수) (인스턴스 필드) (인스턴스 프로퍼티)

 

# 생성자 (Constructor)

 생성자는 클래스를 기반으로 하여 인스턴스를 만드는 역할을 하는 것이다. 인스턴스를 생성할 때 해야할 작업을 담아두는 약속된 메소드가 __construct이고, 이 메소드를 생성자 라도 일컫는다.  그렇다면 코드에서 Constructor는 누구일까?

예제는 다음과 같다.

 

# 객체 생성

$file = new SplFileObject('data.txt');


# new뒤에 있는 SplFileObject(); 가 바로 생성자이다.

이전 예제에서 클래스를 이용하여 객체를 생성하기 위해서는 상기와 같이 코드를 입력해야 한다고 했는데, new뒤에 붙는 클래스 이름에 함수처럼 쓴 저것이 바로 생성자라고 하는 것이다. 

 이러한 생성자를 통해서 인스턴스를 생성할 때,(new SplFileObject();) data.txt라고 하는 상태를 객체에 주입한 것을 확인할 수 있었다. (new SplFileObject('data.txt');) 이것은 객체를 만들 때 필수적인 상태를 처음부터 주입하는 테크닉을 보여주고 있는 것이다.

 또한 하기와 같이 객체를 생성할 때, 상태를 주입하지 않고 인스턴스 변수를 통해서 상태를 주입하는 테크닉역시 학습하였다.

 

# 객체생성

$file = new MyFileObject();
$file -> filename = 'data.txt';

# 객체를 생성할 때 상태를 주입하지 않음 line3
# 객체를 생성하고 상태를 주입함 line4

 

 객체를 생성하고 나서 상태를 주입한다면, 객체가 복잡하거나 거대할 경우 혹은 많은 작업을 할 경우 상태주입의 부재로 인한 오류 혹은, 기타 오류가 발생할 확률이 높아진다. 

 반면에 객체를 생성하면서 동시에 상태를 주입하는 경우에는 인자로서 상태를 받지 않으면 내제되어있는 메소드들이 오류를 일으키기 때문에 생성할 때 반드시 필요한 초기의 데이터( 변수 혹은 상수)를 필수적으로 입력받을 수 있다는 장점이 존재한다.

 

상기의 내용과 같이, 객체가 생성될때 상태를 반드시 주입받기 위해서는( 인자를 받기 위해서는 ) 생성자 라는 것을 통하여 클래스를 생성하면 된다. 이 때 사용되는 개념이 바로 생성자이다.

 

<?php

# 생성자 예제
class MyFileObject() {
    
    function __construct() {
    
    }
}

## __construct() 는 생성자 키워드이다.

 

 생성자는 상기 예제와 같이 클래스에서 인자를 받기 위해서 무언가를 정의할 떄 사용하는 것이고 용법은 __constuct()라는 키워드를 선언하는 방식으로 이루어져있다. 예제는 다음과 같다.

 

<?php

# 생성자 예제
class MyFileObject() {
    # 클래스로 객체가 생성이 되면 생성자를 먼저 호출하여 초기화를 함
    function __construct($fname) {
    	# 생성자는 객체가 생성될 때 인자로 받은 값을 $fname이라는 변수로 전달받음
        $this -> filename = $fname;
        # fname에 전달받은 값을 filename에 할당하고, 해당클래스(MyFileObject)클래스에서는
        # filename을 this라는 것으로 사용할 것임.
    }
}

 생성자는 클래스로 객체가 생성되었을 때, 가장먼저 호출되어 생성되는 객체를 초기화 하는 함수로서, __construct()라는 키워드를 이용하여 선언한다.

 우리가 객체를 통하여 어떠한 것을 제어하려고 한다면, 객체에 상태(인자)를 주입받는 것이 오류의 확률을 낮춰주고 보다 정확하게 프로그래밍을 할 수 있는 상태가 된다고 할 수 있다. 따라서 클래스에 인자를 받을 수 있도록 설계를 해야 하는데, 이것을 생성자로서 할 수 있는 것이다.

 생성자는 상기 코드와 같이 이루어져 있다. 외부에서 값을 받을때, __construct의 인자로 외부의 값을 받게 되고, 그것을 다시 내부 클래스의 변수에 할당을 해주는 방식으로 이루어져 있는것이다.

 상기 코드에서.

    function __construct($fname) {
     # 생성자는 객체가 생성될 때 인자로 받은 값을 $fname이라는 변수로 전달받음
        $this -> filename = $fname;
        # fname에 전달받은 값을 filename에 할당하고, 해당클래스(MyFileObject)클래스에서는
        # filename을 this라는 것으로 사용할 것임.