เป็นไปได้ไหมที่จะสร้างคลาสสแตติกใน 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 เพื่อความมีสติการทดสอบและเพื่อความสามารถในการปรับขนาดของคลาสแบบคงที่ควรจะไร้สัญชาติโดยสิ้นเชิง ใช้เป็นส่วนอำนวยความสะดวกในการเข้าถึงได้ดีที่สุดสำหรับวัตถุหรือตัวห่อหุ้มยูทิลิตี้สำหรับผู้ช่วยหรือสิ่งปลูกสร้างที่คล้ายกันหากพวกมันถูกใช้งาน
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 Utility :: 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 เธรดเดี่ยวและไม่ชอบเอาสิทธิ์เหมือนโหนด?
John Little

53

นอกเหนือจากคำตอบของ 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
นี่เป็นวิธีการที่ยอดเยี่ยม แต่ฟังก์ชั่นการสร้างไม่สามารถนำมาใช้ได้หาก Singelton ของคุณสืบทอดจากวัตถุบางอย่างที่ต้องใช้ตัวสร้างสาธารณะ
Eric Herlitz

4
@EricHerlitz คำถามนี้ไม่เกี่ยวกับ singletons มันเกี่ยวกับคลาสที่คงที่ ทำไมคุณต้องการสร้างคลาสแบบสแตติกที่สืบทอดจากคลาสที่หมายถึงอินสแตนซ์
Mark Amery

3
การประกาศคลาสอย่างเท่าเทียมกันเป็นนามธรรมโดยป้องกันไม่ให้อินสแตนซ์และยังอนุญาตการเรียกไปยังเมธอดสแตติก
bstoney

24

คุณสามารถมีคลาสเหมือน "แบบคงที่" เหล่านั้นได้ แต่ฉันคิดว่าสิ่งที่สำคัญจริง ๆ ขาดหายไป: ใน php คุณไม่มีแอปพลิเคชันวงจรดังนั้นคุณจะไม่ได้รับคงที่ (หรือซิงเกิล) จริงในใบสมัครทั้งหมดของคุณ ...

ดูSingleton ใน PHP


1
Static Classes และ Singletons เป็นเพียง 2 สิ่งที่แตกต่างกัน
Max Cuttins

4
final Class B{

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

โครงสร้างของ b เรียกว่าตัวจัดการ singeton คุณยังสามารถทำได้ใน a

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

นี่คือการใช้ซิงเกิล $a = a::getA(...);


3

โดยทั่วไปฉันชอบที่จะเขียนคลาสที่ไม่คงที่เป็นประจำและใช้คลาสโรงงานเพื่ออินสแตนซ์อินสแตนซ์ของวัตถุ

วิธีนี้ตัวสร้างและ destructor ทำงานตามปกติและฉันสามารถสร้างอินสแตนซ์ที่ไม่ใช่แบบคงที่เพิ่มเติมได้ถ้าต้องการ (ตัวอย่างเช่นการเชื่อมต่อฐานข้อมูลครั้งที่สอง)

ฉันใช้สิ่งนี้ตลอดเวลาและเป็นประโยชน์อย่างยิ่งสำหรับการสร้างตัวจัดการเซสชันเก็บ DB ที่กำหนดเองเช่นเมื่อหน้ายุติ destructor จะผลักเซสชั่นไปยังฐานข้อมูล

ข้อดีอีกอย่างคือคุณสามารถเพิกเฉยต่อคำสั่งซื้อที่คุณเรียกว่าสิ่งต่าง ๆ เพราะทุกอย่างจะถูกติดตั้งตามความต้องการ

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
นี่เป็นรูปแบบการใช้งานแบบซิงเกิลและไม่ควรใช้ - ติดกับการฉีดพึ่งพาแทนซึ่งสามารถทดสอบได้และทำให้ง่ายต่อการดีบัก
โทมัสแฮนเซน

1
คุณสามารถยกตัวอย่างของวิธีการใช้การฉีดพึ่งพาสำหรับคำตอบนี้และวิธีที่ทำให้ทดสอบได้มากขึ้น?
cjsimon

2

ไม่สามารถกำหนดวัตถุแบบคงที่ แต่ใช้งานได้

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

1
Andreas Niedermair: นั่นเป็นวิธีการทำงานของ php (แอพพลิเคชั่น = คำขอเดียว) แต่ singleton (หนึ่งที่มีชีวิตอยู่ในคำขอ) เป็น possebility ใน php (ใน php a singleton เป็นวัตถุที่มี 1 อินสแตนซ์ (ภายใน app- รอบ)
borrel
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.