PHP'de statik sınıflar oluşturmak mümkün mü (C # gibi)?


139

Ben PHP statik bir sınıf oluşturmak ve bu C # gibi davranmasını istiyorum, bu yüzden

  1. Kurucu otomatik olarak sınıfa yapılan ilk çağrıda çağrılır
  2. Örneklemeye gerek yok

Bu tür bir şey ...

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

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

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

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

Statik bir sınıfın nasıl olması gerektiğini kısaca açıklar mısınız? Bir Yardımcı Programın uygulanması mı?
xtofl

Sadece kendi fikrimi ortaya atıyorum, ancak PHP'deki tecrübemden, akıl sağlığı, test edilebilirlik ve ölçeklenebilirlik adına, statik sınıflar tamamen vatansız olmalı, nesne yönelimli olandan daha işlevsel bir programlama benzeri api sunmalı ve genellikle en iyi şekilde tam olarak cisimlendirilmiş nesneler için erişilebilirlik cepheleri veya yardımcılar veya benzer yapılar için kullanılsalar bile yardımcı paketler olarak kullanılır.
mopsyd

Yanıtlar:


200

PHP'de statik sınıflara sahip olabilirsiniz, ancak yapıcıyı otomatik olarak çağırmazlar (denerseniz aradığınızda self::__construct()bir hata alırsınız).

Bu nedenle bir initialize()işlev oluşturmanız ve her yöntemde çağırmanız gerekir:

<?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
Ben sık sık sadece bir yerde fonksiyonları sarmak için bunu yapmak. IE Yardımcı Programı :: doSomethingUseful ();
smack0007

16
Bunun yerine, ortak bir işlev Therefore you'd have to create an initialize() function and call it in each method:yapmak initializeve sınıfın ilanından hemen sonra çağırmak daha kolay olurdu .
chacham15

4
Bunun oldukça eski olduğunu biliyorum, ama şimdi sihirli __callStatic kullanabilirsiniz, bu yüzden herhangi bir statik yöntemi ya da herhangi bir şeyi çağırdığınızda __callStatic, ilk olarak çağıracak , orada başlatılıp başlatılmadığını ve sonra self::$methodne yaptığını ya da ne çağırıyorsan görebileceksin . Hala yöntemi doğrudan çağırıyorsa, her şeyi özel olarak değiştirmeyi deneyin ve oraya bakın.
matiaslauriti

1
İki iş parçacığı aynı anda selam çağırırsa ne olur? Senkronizasyon olmadığından, ilk kez iki kez çağrılmaz (bu durumda tamam, ancak diğer birçok durumda olmaz). Yoksa php tek iş parçacıklı ve düğüm gibi preemptif değil mi?
John Little

53

Greg'in cevabına ek olarak, kurucuyu özel olarak ayarlamanızı, böylece sınıfı somutlaştırmanın imkansız olmasını tavsiye ederim.

Benim düşünceme göre bu Greg'inkine dayanan daha eksiksiz bir örnek:

<?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
Bu harika bir yaklaşımdır, ancak singelton'unuz bir kamu kurucusu gerektiren belirli nesnelerden miras alırsa, yapı işlevi uygulanamaz.
Eric Herlitz

4
@EricHerlitz Bu soru singletonlarla ilgili değil, statik sınıflarla ilgili. Neden somutlaştırılması istenen bir sınıftan miras alan statik bir sınıf oluşturmak istesin ki?
Mark Amery

3
Sınıfın soyut olarak eşit olarak ilan edilmesi, sınıfın somutlaştırılmasını önler ve yine de statik yöntemlere çağrı yapılmasına izin verir.
bstoney

24

"statik" benzeri sınıflara sahip olabilirsiniz. ama sanırım, gerçekten önemli bir şey eksik: php'de bir uygulama döngüsüne sahip değilsiniz, bu yüzden tüm uygulamanızda gerçek bir statik (veya singleton) elde edemezsiniz ...

PHP'de Singleton'a bakınız


1
Statik Sınıflar ve Tektonlar sadece 2 farklı şeydir.
Max Cuttins

4
final Class B{

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

b yapısında bir singeton işleyicisi calld olduğunu da bir

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

bu singleton kullanımı $a = a::getA(...);


3

Genelde düzenli statik olmayan sınıflar yazmayı ve nesnenin tek (sudo statik) örneklerini örneklemek için bir fabrika sınıfı kullanmayı tercih ederim.

Bu şekilde yapıcı ve yıkıcı normal şekilde çalışır ve dilersem ek statik olmayan örnekler oluşturabilirim (örneğin ikinci bir DB bağlantısı)

Bunu her zaman kullanıyorum ve özellikle sayfa sonlandırıcıyı sonlandırdığında oturumu veritabanına itecek gibi özel DB deposu oturum işleyicileri oluşturmak için kullanışlıdır.

Diğer bir avantaj, her şeyi talep üzerine ayarlanacağı için, şeyleri çağırdığınız sırayı göz ardı edebilirsiniz.

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 sınıfı ...

class clsDB {

    $regular_public_variables = "whatever";

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

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

Kullanmak istediğiniz her yerde arayın ...

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

Sonra tüm yöntemleri statik olmayan olarak ele alın (çünkü bunlar)

echo $static_instance->getvar();

1
Bu aslında tekil bir desen uygulamasıdır ve gerçekten kullanılmamalıdır - bunun yerine bağımlılık enjeksiyonuna sadık kalın, test edilebilir ve hata ayıklamayı kolaylaştırır.
Thomas Hansen

1
Bu cevap için bağımlılık enjeksiyonunun nasıl kullanılacağına ve bunun nasıl daha test edilebilir hale getirileceğine dair bir örnek verebilir misiniz?
cjsimon

2

nesne statik olarak tanımlanamıyor ancak bu çalışıyor

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

1
Andreas Niedermair: bu php nasıl çalışır (app-cycle = tek bir istek) Ama bir singleton (istek içinde yaşayan bir) php bir olasılıktır (php bir singleton 1 örneği olan bir nesnedir (app- döngüsü)
Aralık'ta
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.