Menu

PHP 클래스와 객체: 속성, 메서드, $this

PHP 클래스는 class Name { }로 선언하는 설계도이고, new Name()은 그것으로 객체를 만듭니다. 속성, 메서드, $this, public/private/protected, 타입이 있는 속성과 readonly 속성, __toString, 객체를 대입해도 복사되지 않는 이유를 알아봅니다.

이 페이지에는 실행 가능한 에디터가 있습니다 - 편집하고 실행하면 결과를 바로 볼 수 있습니다.

PHP 클래스는 class Name { ... }로 선언하며 속성(변수)과 메서드(함수)를 담습니다. new Name()은 그것으로 객체를 만들고, ->로 속성을 읽거나 메서드를 호출합니다: $user->name, $user->greet().

클래스는 설계도이고, 객체는 그것으로 만든 하나의 물건입니다. 한 클래스로 필요한 만큼 객체를 만들 수 있고, 각 객체는 자신의 속성 값을 가집니다.

속성과 메서드

속성은 접근 제어 키워드, 선택적인 타입, 선택적인 기본값과 함께 선언합니다. 메서드는 클래스 안의 함수입니다. 메서드 안에서 $this는 메서드가 호출된 객체이므로 $this->balance는 그 객체의 잔액을 읽습니다.

각 객체는 자신의 $balance를 가지므로 $a에 입금해도 $b는 바뀌지 않습니다. new 다음에 속성을 하나씩 설정하는 것은 번거로우므로, 대신 생성자가 시작 값을 인수로 받습니다.

public, private, protected

접근 제어는 누가 속성을 건드리거나 메서드를 호출할 수 있는지 정합니다.

키워드접근 가능한 곳
public어디서나
protected클래스 자신과 그것을 상속하는 클래스
private선언한 클래스 안에서만

속성을 private으로 만들고 메서드를 노출하는 것이 클래스가 자신의 규칙을 지키는 방법입니다. 여기서 잔액은 잘못된 금액을 거부하는 deposit()과 withdraw()를 통해서만 바뀔 수 있습니다.

클래스 바깥에서 private 속성을 읽는 것은 경고가 아니라 Error입니다.

타입이 있는 속성과 초기화되지 않은 값

기본값이 없는 타입 있는 속성은 초기화되지 않은 상태로 시작하며, 이는 null과 다릅니다. 무언가를 대입하기 전에 읽으면 Error를 던집니다. 기본값을 주거나, 생성자에서 대입하거나, ?Type과 = null로 nullable하게 만드세요.

타입은 대입할 때 강제됩니다. 기본(엄격하지 않은) 모드에서 $p->stock = '7'은 숫자 문자열을 7로 변환하고, $p->stock = 'many'는 TypeError를 던집니다.

readonly 속성

readonly 속성(PHP 8.1)은 클래스 안에서 한 번 쓸 수 있고 그 뒤로는 다시 쓸 수 없습니다. 금액이나 ID 같은 값 객체를 만드는 일반적인 방법입니다. PHP 8.2는 모든 속성을 readonly로 만드는 readonly class를 추가했습니다.

readonly 속성은 타입이 있어야 하고 기본값을 가질 수 없습니다. 바뀐 복사본이 필요하면 예전 객체를 고치는 대신 새 객체를 만드세요(new Order('B-2002')).

__toString으로 객체 출력하기

echo $object는 클래스가 __toString()을 정의했을 때만 동작합니다. 이 메서드는 객체가 텍스트로 취급될 때마다 PHP가 쓸 문자열을 반환합니다. echo, 문자열 연결, "{$object}" 등입니다.

__toString이 없으면 echo $object는 Error("Object of class Money could not be converted to string")를 던집니다. 디버깅에는 print_r()과 var_dump()가 어떤 객체에서든 동작하고 private 속성도 보여 줍니다. var_dump와 print_r을 참고하세요.

객체를 대입해도 복사되지 않는다

배열에 익숙한 사람들이 가장 많이 겪는 실수입니다. 배열을 대입하면 복사됩니다. 객체를 대입하면 핸들만 복사되어 두 변수가 같은 객체를 가리킵니다.

clone은 얕은 복사를 합니다. 속성이 다른 객체를 담고 있으면 두 복사본이 그 안쪽 객체를 여전히 공유합니다. ===는 같은 객체일 때만 참이고, ==는 같은 클래스의 두 객체의 속성 값을 비교합니다. 객체를 함수에 넘기는 것도 대입과 똑같이 동작하므로, 함수는 받은 객체를 바꿀 수 있습니다.

자주 묻는 질문

PHP에서 클래스로 객체를 만들려면 어떻게 하나요?

클래스 이름과 함께 new를 쓰세요: $user = new User();. 클래스에 생성자가 있으면 new User('Ada')처럼 괄호 안에 인수를 넘기세요. 그다음 화살표 연산자로 메서드를 호출하고 속성을 읽습니다: $user->name, $user->greet().

PHP에서 $this는 무엇을 뜻하나요?

$this는 현재 메서드가 호출된 객체입니다. $ada->greet() 안에서 $this는 $ada이므로 $this->name은 Ada의 이름을 읽습니다. 정적이 아닌 메서드 안에서만 존재합니다.

PHP에서 public, private, protected의 차이는 무엇인가요?

public 멤버는 어디서든, private 멤버는 선언한 클래스 안에서만, protected 멤버는 그 클래스와 자식 클래스에서 쓸 수 있습니다. 바깥에서 private 속성을 읽으면 Error를 던집니다: Cannot access private property.

PHP에서 객체는 참조로 전달되나요?

변수는 객체 자체가 아니라 객체에 대한 핸들을 담습니다. $b = $a;는 핸들을 복사하므로 두 변수가 같은 객체를 가리키고, $b를 통한 변경이 $a에서도 보입니다. 독립된 복사본을 얻으려면 $b = clone $a;를 쓰세요.

PHP의 readonly 속성은 무엇인가요?

public readonly string $id;로 선언한 속성(PHP 8.1+)은 클래스 안에서 한 번 설정할 수 있고 그 뒤로는 바꿀 수 없습니다. 두 번째로 쓰면 Error를 던집니다: Cannot modify readonly property.

Coddy 프로그래밍 언어 일러스트

Coddy로 코딩 배우기

시작하기