로그인 회원가입
모두인포
전체IT경제사회생활스포츠시사여행연애

PHP 인스턴스 변수

lmkfox · 2025-08-26 · 조회 0
PHP 인스턴스 변수
1) 인스턴스 변수란? - 클래스의 각 객체가 개별적으로 보유하는 상태입니다. - 문법적으로는 프로퍼티(property) 라고 부르며, static이 아닌 프로퍼티가 인스턴스 변수입니다. - 반대로 static 프로퍼티는 클래스 전체가 공유합니다(인스턴스 변수 아님). class Counter { // 인스턴스 변수(객체마다 따로 있음) private int $value = 0; public function inc(int $step = 1): void { $this->value += $step; } public function value(): int { return $this->value; } } $a = new Counter(); $b = new Counter(); $a->inc(2); echo $a->value(); // 2 echo $b->value(); // 0 ← 서로 다른 상태 2) 선언 방법과 가시성(접근 제어자) class User { public int $id; // 어디서나 접근 가능(권장 X) protected string $role; // 자기 자신 + 자식 클래스에서 접근 private string $name; // 해당 클래스 내부에서만 접근 public function __construct(int $id, string $name, string $role = 'user') { $this->id = $id; $this->name = $name; $this->role = $role; } public function name(): string { return $this->name; } // 게터 } - 기본 권장: 프로퍼티는 private, 읽기/변경은 메소드로 캡슐화. - 외부 직접 접근이 꼭 필요할 때만 public을 신중히 사용. 3) 타입 선언(필수 습관) PHP 7.4+부터 타입드 프로퍼티를 지원합니다. class Product { public int $id; public string $name; public ?string $description = null; // nullable public int|float $price; // union 타입(8.0+) public function __construct(int $id, string $name, int|float $price) { $this->id = $id; $this->name = $name; $this->price = $price; } } - 타입이 있는 프로퍼티는 초기화 전에 접근하면 오류가 납니다. 생성자에서 반드시 채우세요. - 프로퍼티 기본값은 상수 표현식만 가능(객체 생성 등은 안 됨) → 생성자에서 처리. 4) 초기화 패턴 4.1 일반적인 방식 class Point { private int $x; private int $y; public function __construct(int $x, int $y) { $this->x = $x; $this->y = $y; } } 4.2 생성자 프로퍼티 승격(PHP 8.0+) 생성자 매개변수에 접근 제어자와 타입을 붙여 선언+초기화를 한 줄로 처리합니다. class Point { public function __construct( private int $x, private int $y, ) {} public function x(): int { return $this->x; } public function y(): int { return $this->y; } } 4.3 지연 초기화/검증 class Session { private ?string $token = null; public function token(): string { if ($this->token === null) { $this->token = bin2hex(random_bytes(16)); } return $this->token; } } 5) 읽기 전용(Readonly) 인스턴스 변수(PHP 8.1+) 생성 이후 수정 불가한 불변 상태가 필요할 때 사용합니다. final class Money { public function __construct( public readonly int $amount, public readonly string $currency ) {} } $m = new Money(1000, 'KRW'); // $m->amount = 2000; // 오류: readonly는 재할당 불가 6) 접근/수정 방법 - 클래스 내부: $this->prop - 외부: $obj->prop (단, public이어야 함) - 보통은 메소드로 캡슐화합니다. class Profile { private string $nickname; public function __construct(string $nickname) { $this->nickname = $nickname; } public function rename(string $new): void { if ($new === '') throw new InvalidArgumentException('empty'); $this->nickname = $new; } public function nickname(): string { return $this->nickname; } } $p = new Profile('kim'); $p->rename('lee'); echo $p->nickname(); // lee 7) nullsafe 연산자와 체이닝(PHP 8.0+) 객체가 null일 수 있을 때 안전하게 프로퍼티/메소드에 접근합니다. $city = $user?->address?->city; // 중간이 null이면 전체가 null 8) 동적 프로퍼티(지양) - 예전엔 선언하지 않은 프로퍼티를 런타임에 추가해도 됐지만, PHP 8.2+에서 폐지(Deprecated) 경고가 발생합니다. - 꼭 필요하면 #[\AllowDynamicProperties] 또는 stdClass 활용, 권장 대안은 명시적 선언 혹은 __get/__set 매직 메소드. class Box { private array $data = []; public function __get(string $name) { return $this->data[$name] ?? null; } public function __set(string $name, $value) { $this->data[$name] = $value; } } 9) static 프로퍼티와의 차이 class Example { public static int $count = 0; // 모든 인스턴스가 공유 public function __construct(private int $id) { self::$count++; } } $a = new Example(1); $b = new Example(2); echo Example::$count; // 2 - 인스턴스 변수: 각 객체가 독립 보유 - static 변수: 클래스 단위로 공유 - 상태를 공유해야 하는 특수한 경우가 아니라면 static 남용 금지. 10) 상속과 인스턴스 변수 - 부모의 protected 프로퍼티는 자식에서 사용 가능. - 같은 이름의 프로퍼티를 재선언하는 일은 피하세요(혼동과 호환성 이슈 유발). - 공통 상태는 부모에 protected로 두고, 동작은 자식에서 확장하는 구조가 안전합니다. 11) 컬렉션/객체 타입, 제네릭 표기 관례 PHP 언어 차원의 제네릭은 없지만, DocBlock으로 의도를 명시합니다. /** @var list<User> */ private array $members = []; /** @param list<User> $members */ public function __construct(array $members = []) { $this->members = $members; } 정적 분석기(phpstan/psalm)와 IDE가 이 정보를 활용합니다. 12) 실무 예제: 불변 값 + 가변 엔티티 final class Email { public function __construct(public readonly string $value) { if (!filter_var($value, FILTER_VALIDATE_EMAIL)) { throw new InvalidArgumentException('invalid email'); } } } final class Account { public function __construct( private int $id, private Email $email, private DateTimeImmutable $createdAt = new DateTimeImmutable() ) {} public function changeEmail(Email $email): void { $this->email = $email; // 도메인 규칙 검증은 Email에서 담당 } public function id(): int { return $this->id; } public function email(): Email { return $this->email; } public function createdAt(): DateTimeImmutable { return $this->createdAt; } } 포인트 - **값 객체(Email)**는 readonly로 불변. - **엔티티(Account)**는 도메인 규칙을 따르며 인스턴스 변수를 통해 상태 변화를 관리. 13) 흔한 실수와 체크리스트 - 타입드 프로퍼티를 초기화 전에 접근 → 오류. 생성자/팩토리에서 반드시 채우기. - 선언 없이 $obj->foo = ... 추가(동적 프로퍼티) → 8.2+에서 경고. 반드시 선언. - 외부에서 public 프로퍼티를 직접 바꿈 → 불변식 깨짐. 메소드로 검증/수정. - 프로퍼티 기본값에 new나 함수 호출 사용 → 불가. 생성자에서 처리. - 공유 상태가 필요한 게 아닌데 static 사용 → 테스트/동시성 문제 유발. 14) 요약 - 인스턴스 변수는 객체마다 독립된 상태를 담는 프로퍼티입니다. - private + 타입 선언 + 생성자 초기화가 기본기. - 변경을 통제하고 싶다면 게터/세터 대신 의미 있는 도메인 메소드를 제공하세요. - 불변이 적합하면 readonly를, 동적 필드가 필요하면 명시적 선언 또는 매직 메소드로.

댓글

아직 댓글이 없습니다.

로그인 후 댓글을 남길 수 있습니다.