written: Nov 07 2007
정적 멤버(static member)
PHP5에서 정적 멤버를 static 키워드를 이용하여 정의하여 사용할 수 있습니다.
visibility static $변수이름 = 변수값;
visibility static function 함수이름(인수리스트) { 함수내용 };
visibility static function 함수이름(인수리스트) { 함수내용 };
visibility 위치에는 정적 멤버의 가시범위(visibility)를 제한할 수 있는 PPP 접근제한자(private/protected/public access modifier)를 지정할 수 있습니다. 생략하면 PHP4와의 호환성을 고려하여 멤버를 public로 처리합니다.
정적 멤버는 객체를 생성하지 않고도 접근할 수 있도록 해줍니다.
[code php;gutter:false]
<?php
class Foo
{
public static $my_static = 'foo';
public function staticValue() {
return self::$my_static;
}
}
class Bar extends Foo
{
public function fooStatic() {
return parent::$my_static;
}
}
print Foo::$my_static . "\n";
$foo = new Foo();
print $foo->staticValue() . "\n";
print Bar::$my_static . "\n";
$bar = new Bar();
print $bar->fooStatic() . "\n";
?>
[/code]
< 예제출처:php.net >
정적 멤버 변수(static member variable)
[code php;gutter:true]
<?php
class test_class {
public static $static_var = "my static variable's value\n";
public function get_static() {
return self::$static_var;
}
public function set_static($val) {
self::$static_var = $val . "\n";
}
}
print test_class::$static_var;
$obj = new test_class();
$obj->set_static("my static variable's new value");
$obj2 = new test_class();
print $obj2->get_static();
?>
[/code]
위에서 볼 수 있듯이 정적 멤버 변수로 선언된 변수는 어느 인스턴스에서 수정되어도 모든 인스턴스에 적용이 됩니다. 위에서 17번째 줄에 보이듯이 $obj 인스턴스에 의해 수정된 정적 멤버 변수는 $obj2의 다른 인스턴스에도 모두 영향을 미칩니다.
출력 결과는 아래와 같습니다.
my static variable's value
my static variable's new value
my static variable's new value
클래스 상수와 마찬가지로 정적 멤버 변수는 객체를 통해서 접근할 수 없습니다. 이것은 정적 멤버 함수가 객체를 통해서 접근할 수 있는 것과 다르다는 점에 주의해야 합니다. 따라서 클래스 내부에서만 사용되는 $this 키워드를 이용해서도 접근이 불가능하며 반드시 범위지정연산자(::) 앞에 클래스명, self 또는 parent 키워드를 이용해서 접근해야만 합니다.
[code php;gutter:true]
<?php
class test_class {
public static $static_var = "my static variable's value\n";
}
$obj = new test_class();
print $obj->static_var;
// Notice: Undefined property: test_class::$static_var in xxx.php on line 8
// $obj::static_var is not possible
// Parse error: parse error, unexpected T_PAAMAYIM_NEKUDOTAYIM
// in xxx.php on line nnn
?>
[/code]
정적 멤버 함수(static method)
정적 멤버 함수는 객체를 생성하지 않고도 접근할 수 있도록 해줍니다.
[code php;gutter:false]
<?php
class my_class {
public static function hello_world() {
print "Hello, world";
}
}
my_class::hello_world();
?>
[/code]
생성된 객체를 통해서 멤버에 접근할 수 있습니다.
[code php;gutter:false]
<?php
class my_class {
public static function hello_world() {
print "Hello, world";
}
}
$obj = new my_class;
$obj->hello_world();
?>
[/code]
그러나 객체 생성없이 접근하는 경우도 있기 때문에 의사 변수(pseudo variable) $this를 정적 멤버 함수 내에서 사용해서는 안됩니다.
[code php;gutter:false]
<?php
class my_class {
public static function hello_world() {
print "Hello, world";
}
public static function hello() {
$this->hello_world();
}
}
$obj = new my_class;
$obj->hello();
// Fatal error: Using $this when not in object context in xxx.php on line 8
?>
[/code]
정적멤버가 아닌 메쏘드를 정적으로 호출하는 것은 E_STRICT 레벨의 경고를 발생시킵니다.
[code php;gutter:false]
<?php
class my_class {
public function hello_world() {
print "Hello, world";
}
}
error_reporting(E_ALL | (defined('E_STRICT')? E_STRICT : 0));
my_class::hello_world();
// Strict Standards: Non-static method my_class::hello_public()
// should not be called statically in xxx.php on line 10
?>
[/code]
싱글턴 패턴(singleton pattern)
정적 멤버 변수를 가장 유용하게 활용하는 곳이 있다면 디자인 패턴 중 싱글턴 패턴(singleton pattern)일 것입니다.
싱글턴 패턴은 프로그램이 동작할 때 클래스의 인스턴스가 반드시 하나만 존재하도록 해주는 패턴으로 매우 중요한 요소입니다만 PHP4에서는 정적멤버, PPP 접근제한자, 인터페이스 등의 객체지향언어의 핵심기능을 빠진 상태에서 구현이 사실상 불가능하였습니다.
PHP5부터 제공되기 시작한 정적멤버 및 PPP 접근제한자 등의 특성을 이용하여 디자인 패턴 중에서도 가장 널리 사용되는 싱글턴 패턴을 구현해 보겠습니다. 소스는 php.net의 document에서 발췌하여 수정한 것입니다.
[code php;gutter:false]
<?php
class Example {
// Hold an instance of the class
private static $instance;
// Prevents direct creation of object
private function __construct() {
echo 'I am constructed';
}
// The singleton method
public static function singleton() {
if (!isset(self::$instance)) {
$c = __CLASS__;
self::$instance = new $c;
}
return self::$instance;
}
// Example method
public function bark() {
echo 'Woof!';
}
// Prevent users to clone the instance
private function __clone() { }
}
//This allows a single instance of the Example class to be retrieved.
// This will always retrieve a single instance of the class
$test = Example::singleton();
$test->bark();
?>
[/code]
클래스 밖에서 singleton() 메쏘드를 이용하지 않고 아래 코드와 같이 new 또는 clone 연산자를 이용하여 객체를 생성하려면 Fatal 에러가 발생하기 때문에 프로그램상에서 인스턴스는 단 1개만 존재할 수 있습니다.
[code php;gutter:false]
<?php
class Example {
// Hold an instance of the class
private static $instance;
// Prevents direct creation of object
private function __construct() {
echo 'I am constructed';
}
// The singleton method
public static function singleton() {
if (!isset(self::$instance)) {
$c = __CLASS__;
self::$instance = new $c;
}
return self::$instance;
}
// Example method
public function bark() {
echo 'Woof!';
}
// Prevent users to clone the instance
private function __clone() { }
}
// This would fail because the constructor is private
$test = new Example;
// Fatal error: Call to private Example::__construct()
// from invalid context in xxx.php on line 30
// This will issue an E_USER_ERROR.
$test_clone = clone $test;
// Fatal error: Call to private Example::__clone() from context ''
// in xxx.php on line 35
?>
[/code]
다중쓰레드(multi thread)를 지원하지 않는 PHP에서야 별 상관없는 이야기이지만 자바와 같이 다중쓰레드를 지원하는 프로그램에서는 위의 코드도 완벽하지 않습니다. 여러 개의 쓰레드가 거의 동시에 singleton() 메쏘드를 호출한다고 가정한다면 순간적으로 여러 개의 인스턴스가 생성될 수 있습니다. 따라서 singleton() 메쏘드는 단 하나의 쓰레드만 접근할 수 있도록 제한할 필요가 있습니다. 이를 위한 연산자가 synchronized입니다. 다음은 "Java 언어로 배우는 디자인 패턴 입문 - (주)영진닷컴" p.445에 나오는 synchronized 연산자를 적용한 싱글턴 페턴 클래스 예제입니다.
[code java;gutter:false]
public class Singleton {
private static Singleton singleton = null;
private Singleton() {
System.out.println("인스턴스를 생성했습니다");
slowdown();
}
public static synchronized Singleton getInstance() {
if (singleton == null) {
singleton = new Singleton();
}
return singleton;
}
private void slowdown() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
}
}
[/code]
위 소스에서 slowdown() 메쏘드는 다중쓰레드에 의해 여러 개의 인스턴스가 생성되는지 확인하기 위해 프로그램의 동작 속도를 일부로 느리게 하기 위해 첨가된 코드입니다.
'phpclass > 객체모델' 카테고리의 다른 글
{PHP5 객체모델}11.Final 키워드 (0) | 2005.10.11 |
---|---|
{PHP5 객체모델}10.인터페이스 (0) | 2005.10.11 |
{PHP5 객체모델}08.클래스 상수 (0) | 2005.10.11 |
{PHP5 객체모델}07.추상클래스 (0) | 2005.10.11 |
{PHP5 객체모델}06.범위지정연산자(::) (0) | 2005.10.11 |