PHP에서 정적 클래스를 만들 수 있습니까 (C # 에서처럼)?


139

PHP에서 정적 클래스를 만들고 C #에서와 같이 동작하도록하고 싶습니다.

  1. 생성자는 클래스를 처음 호출 할 때 자동으로 호출됩니다.
  2. 인스턴스화가 필요하지 않습니다

이런 종류의 ...

static class Hello {
    private static $greeting = 'Hello';

    private __construct() {
        $greeting .= ' There!';
    }

    public static greet(){
        echo $greeting;
    }
}

Hello::greet(); // Hello There!

정적 클래스가 어떻게 동작해야하는지 간단히 설명해 주시겠습니까? 유틸리티의 구현입니까?
xtofl

PHP에 대한 내 경험, 정신 건강, 테스트 가능성 및 확장 성을 위해 정적 클래스는 거의 완전히 상태가 없어야하며 객체 지향 클래스보다 더 기능적인 프로그래밍과 같은 API를 제공해야합니다. 도우미 또는 이와 유사한 구성 요소가 전혀 사용되지 않는 경우 완전히 인스턴스화 된 개체 또는 유틸리티 래퍼에 대한 접근성 파사드로 사용하는 것이 가장 좋습니다.
mopsyd

답변:


200

PHP에서 정적 클래스를 가질 수 있지만 생성자를 자동으로 호출하지는 않습니다 (시도하고 호출 self::__construct()하면 오류가 발생합니다).

따라서 initialize()함수 를 작성하여 각 메소드에서 호출해야합니다.

<?php

class Hello
{
    private static $greeting = 'Hello';
    private static $initialized = false;

    private static function initialize()
    {
        if (self::$initialized)
            return;

        self::$greeting .= ' There!';
        self::$initialized = true;
    }

    public static function greet()
    {
        self::initialize();
        echo self::$greeting;
    }
}

Hello::greet(); // Hello There!


?>

20
나는 종종 한곳에서 모든 기능을 마무리하기 위해이 작업을 수행합니다. IE 유틸리티 :: doSomethingUseful ();
smack0007

16
대신 공개 함수 Therefore you'd have to create an initialize() function and call it in each method:를 만들고 initialize클래스 선언 직후에 호출하는 것이 더 쉬울 것 입니다.
chacham15

4
나는이 꽤 오래 알고 있지만, 지금 당신은 마법을 사용할 수 __callStatic를 , 처음 호출 할 것이다 당신이 정적 방법 또는 아무것도 호출 할 때, 그래서 __callStatic, 당신이 거기가 초기화 있는지 확인하고 할 수있는 self::$method또는 당신이 무엇을 요구하고있다. 여전히 메소드를 직접 호출하는 경우 모든 것을 개인용으로 변경하고 참조하십시오.
matiaslauriti

1
두 개의 스레드 호출이 동시에 인사하면 어떻게됩니까? 동기화가 없기 때문에 초기화가 두 번 호출되지 않습니다 (이 경우에는 정상이지만 다른 많은 경우에는 그렇지 않습니다). 아니면 PHP는 단일 스레드이며 비 선점 형 노드입니까?
존 리틀

53

Greg의 답변 외에도 클래스를 인스턴스화 할 수 없도록 생성자를 private으로 설정하는 것이 좋습니다.

내 겸손한 견해로는 이것이 Greg의 사례를 기반으로 한 더 완벽한 예입니다.

<?php

class Hello
{
    /**
     * Construct won't be called inside this class and is uncallable from
     * the outside. This prevents instantiating this class.
     * This is by purpose, because we want a static class.
     */
    private function __construct() {}
    private static $greeting = 'Hello';
    private static $initialized = false;

    private static function initialize()
    {
        if (self::$initialized)
            return;

        self::$greeting .= ' There!';
        self::$initialized = true;
    }

    public static function greet()
    {
        self::initialize();
        echo self::$greeting;
    }
}

Hello::greet(); // Hello There!


?>

1
이것은 훌륭한 접근 방식이지만, 생성자가 공용 생성자를 필요로하는 특정 객체에서 상속받은 경우 생성 함수를 구현할 수 없습니다.
Eric Herlitz

4
@EricHerlitz이 질문은 싱글 톤에 관한 것이 아니라 정적 클래스에 관한 것입니다. 인스턴스화하려는 클래스에서 상속되는 정적 클래스를 작성하려는 이유는 무엇입니까?
Mark Amery

3
클래스를 추상으로 선언하면 클래스 화가 방지되고 정적 메소드에 대한 호출이 여전히 허용됩니다.
bstoney

24

"정적"과 같은 클래스를 가질 수 있습니다. 하지만 정말 중요한 것이 빠져 있다고 가정합니다 .php에는 앱 사이클이 없으므로 전체 응용 프로그램에서 실제 정적 (또는 싱글 톤)을 얻지 못합니다 ...

PHP에서 싱글 톤 참조


1
정적 클래스와 싱글 톤은 단지 두 가지입니다.
Max Cuttins

4
final Class B{

    static $staticVar;
    static function getA(){
        self::$staticVar = New A;
    }
}

b의 구조는 단일 처리기라고하며 a에서도 할 수 있습니다.

Class a{
    static $instance;
    static function getA(...){
        if(!isset(self::$staticVar)){
            self::$staticVar = New A(...);
        }
        return self::$staticVar;
    }
}

이것은 싱글 톤 사용입니다 $a = a::getA(...);


3

나는 일반적으로 정적이 아닌 일반 클래스를 작성하고 팩토리 클래스를 사용하여 객체의 단일 (sudo static) 인스턴스를 인스턴스화하는 것을 선호합니다.

이 방법으로 생성자와 소멸자가 정상적으로 작동하며 원하는 경우 추가 비 정적 인스턴스를 만들 수 있습니다 (예 : 두 번째 DB 연결)

나는 이것을 항상 사용하며 페이지가 종료되면 소멸자가 세션을 데이터베이스로 푸시하므로 사용자 지정 DB 저장소 세션 처리기를 만드는 데 특히 유용합니다.

또 다른 장점은 모든 것이 필요할 때 설정되므로 호출하는 순서를 무시할 수 있다는 것입니다.

class Factory {
    static function &getDB ($construct_params = null)
    {
        static $instance;
        if( ! is_object($instance) )
        {
            include_once("clsDB.php");
            $instance = new clsDB($construct_params);   // constructor will be called
        }
        return $instance;
    }
}

DB 클래스 ...

class clsDB {

    $regular_public_variables = "whatever";

    function __construct($construct_params) {...}
    function __destruct() {...}

    function getvar() { return $this->regular_public_variables; }
}

당신이 그것을 사용하고자하는 곳은 그냥 전화 ...

$static_instance = &Factory::getDB($somekickoff);

그런 다음 모든 메소드를 정적이 아닌 것으로 취급하십시오.

echo $static_instance->getvar();

1
이것은 실제로 싱글 톤 패턴 구현이며 실제로 사용해서는 안됩니다. 대신 의존성 주입을 고수하십시오. 테스트 가능하고 디버그하기 쉽습니다.
Thomas Hansen

1
이 답변에 의존성 주입을 사용하는 방법과 더 테스트 할 수있는 방법에 대한 예를 들어 줄 수 있습니까?
cjsimon

2

객체를 정적으로 정의 할 수는 없지만 작동합니다.

final Class B{
  static $var;
  static function init(){
    self::$var = new A();
}
B::init();

1
Andreas Niedermair : php 작동 방식 (app-cycle = 단일 요청) 그러나 싱글 톤 (요청에있는 사람)은 php의 가능성입니다 (php에서 싱글 톤은 1 개의 인스턴스가있는 객체입니다 (앱 내- cycle)
borrel
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.