method 이름 앞에 __
이 붙으면 magic method인데
__construct()
, __destruct()
도 magic method의 일종이다.
class A
{
public function __construct() {
echo __METHOD__ . "\n";
}
public function __destruct() {
echo __METHOD__ . "\n";
}
}
$a = new A();
echo("hi\n");
이러면 출력되는 결과는 아래와 같다.
A::__construct
A::__destruct
hi
<?php
class A
{
public function __construct() {
echo __METHOD__ . "\n";
}
public function __destruct() {
echo __METHOD__ . "\n";
}
}
$a = new A();
unset($a);
echo("hi\n");
이러면 출력되는 결과는 아래와 같다.
A::__construct
A::__destruct
hi
unset함수를 실행했을 때 객체가 release되어서 소멸자가 호출된 것이다.
class A
{
public $message;
public function __construct($message) {
$this->message = $message;
}
}
$a = new A();
위와 같은 코드를 실행시킬 경우,
$a = new A();
부분에서 에러가 난다. (생성자에서 정의한 인자를 넣어주지 않아서.)
PHP Fatal error: Uncaught ArgumentCountError: Too few arguments to function A::__construct()
<?php
class A
{
public function __construct() {
echo __METHOD__ . "\n";
}
public function __destruct() {
echo __METHOD__ . "\n";
}
}
class B extends A
{
}
$b = new B();
class B에서 따로 생성자, 소멸자 함수를 정의하지 않았다면, 객체가 생성되거나 소멸될 때 부모 클래스의 생성자 함수와 소멸자 함수가 실행된다.
위 코드의 결과는 다음과 같다.
A::__construct
A::__destruct
그리고 다른 엄격한 language에서와는 다르게 php는 자식 class에서 생성자 함수를 정의 할 경우, 부모의 생성자 함수가 실행되지 않는다.
그래서 자식 class에서 생성자를 정의(override)할 경우 코드 맨 윗 줄에 아래와 같이 명시적으로 부모 class의 생성자를 불러주는 것이 바람직하다.
class A
{
public function __construct() {
echo __METHOD__ . "\n";
}
public function __destruct() {
echo __METHOD__ . "\n";
}
}
class B extends A
{
public function __construct() {
parent::__construct();
// code ...
}
public function __destruct() {
parent::__destruct();
// code ...
}
}
Final 키워드는 class 안의 method 혹은 class 자체에 사용 가능하다.
final은 말 그대로 거기서 끝이라는 뜻이다. 더이상의 상속이나 재정의가 불가능하도록 명시하는 키워드다.
이 경우 해당 method를 자식 class에서 재정의(override)하지 못한다.
class A
{
public final function foo() {
echo "foo~";
}
}
class B extends A
{
public function foo() {
echo "foofoo~~";
}
}
그래서 위 코드는 에러가 난다.
(Cannot override final method A::foo()
)
이 경우 해당 class자체를 상속받을 수 없게 된다.
final class A
{
}
class B extends A
{
}
그래서 위 코드는 에러가 난다.
(Class B may not inherit from final class (A)
)
class 내부의 visibility를 나타내는 키워드는 세가지다.
<?php
class A
{
public $foo1 = 'foo1';
protected $foo2 = 'foo2';
private $foo3 = 'foo3';
public function bar1() {
echo "bar1\n";
}
protected function bar2() {
echo "bar1\n";
}
private function bar3() {
echo "bar1\n";
}
}
$a = new A();
$a->foo1; // O
$a->foo2; // X (error)
$a->foo3; // X (error)
$a->bar1(); // O
$a->bar2(); // X (error)
$a->bar3(); // X (error)
class A
{
public $foo1 = 'foo1';
protected $foo2 = 'foo2';
private $foo3 = 'foo3';
public function bar1() {
echo "bar1\n";
}
protected function bar2() {
echo "bar1\n";
}
private function bar3() {
echo "bar1\n";
}
}
class B extends A
{
public function test() {
echo $this->foo1; // O
echo $this->foo2; // O
echo $this->foo3; // X (error)
}
}
$b = new B();
$b->test();
class A
{
public $foo1 = 'foo1';
protected $foo2 = 'foo2';
private $foo3 = 'foo3';
public function bar1() {
echo "bar1\n";
}
protected function bar2() {
echo "bar1\n";
}
private function bar3() {
echo "bar1\n";
}
public function test() {
echo $this->foo1; // O
echo $this->foo2; // O
echo $this->foo3; // O
}
}
$a = new A();
$a->test();
class A
{
private $message = 'Hi';
private function __construct() {
echo $this->message . "\n";
}
}
$a = new A(); // X (error)
위 코드의 경우 에러가 난다.
(바깥에서 new 로 객체를 생성했을 때 class A의 생성자 함수가 불리는데 그게 private이기 때문.)
class A
{
private $message = 'Hi';
private function __construct() {
echo $this->message . "\n";
}
public static function create() {
return new self();
}
}
$a = A::create();
위 코드의 경우 class A내부에서 생성자 함수를 불렀기 때문에 에러가 안나고 create 함수를 통해 객체를 받을 수 있다.
( 정상적으로 Hi
가 출력된다.)
위와 같은 구조를 활용하면 Singleton pattern (싱글턴 패턴) 을 만들 수 있다.
Singleton pattern이란 인스턴스를 하나만 만들어서 사용하는 패턴이다.
자원을 아낄 수 있고 인스턴스를 의도치 않게 여러 개 만드는 것을 방지한다.
class A
{
private static $instance;
private function __construct() {
}
public static function create() {
return self::$instance ? : self::$instance = new self();
}
}
$a1 = A::create();
$a2 = A::create();
if($a1 === $a2)
echo "same!";
위 코드는 최종적으로 "same"이 출력된다.
참고로 위 코드의 ?:
연산자는
foo == bar ?: baz;
=== foo == bar ? bar : baz;
다.
잘 보고 있습니다. 감사합니다.