2011-01-17 33 views
8
--- A.php ---- 
require_once 'B.php'; 

class A 
{ 
    public function __constructor($x){...} 

    public function foo() 
    { 
     $b = B::getInstance(); 
     ... 
    } 
} 

--- B.php ---- 
require_once 'A.php'; 

class B extends A 
{ 
    protected static $_instance = null; 

    protected function __construct(){} 

    public static function getInstance() 
    {....} 
} 

PHP chỉ dừng lại giải thích đoạn code ngay khi nó đạt đến dòngkhông thể xác định hàm tạo như được bảo vệ hoặc riêng tư! tại sao?

protected function __construct(){} 

và kết quả đầu ra tất cả mọi thứ trước và không có gì mà có thể đã được gửi đến trình duyệt sau đó.

Và ngay sau khi tôi chỉ mất dòng đó ra, bằng cách thay đổi nó để

// protected function __construct(){} 

tất cả mọi thứ hoạt động tốt !?

Tôi không hiểu.

Bất kỳ ý tưởng nào?

+1

bạn có thẻ mở php trong các tập tin, ví dụ như chúng bắt đầu bằng ' Gordon

+1

Phương thức __construct() sẽ cần phải được công khai vì nó được truy cập (publically) khi một cá thể của lớp được tạo ra. –

+0

Mã giả của bạn không có bất kỳ vấn đề rõ ràng nào do đó các sự cố có nhiều khả năng nhất trong mã thực của bạn. Nếu PHP ngừng chạy và không hiển thị bất kỳ thông báo lỗi nào, bạn có thể cần phải bật báo cáo lỗi đầy đủ. Vui lòng hỏi chi tiết nếu bạn không biết làm thế nào. –

Trả lời

12

Tôi vừa tạo một tệp thử nghiệm đơn giản để xác nhận xem điều này có xảy ra trên máy của tôi không và tôi nghĩ rằng tôi đã tìm thấy câu trả lời. Đi đoạn mã sau:

<?php 
error_reporting(E_ALL | E_STRICT); 
class Foo { 
    public function __construct() { 
    } 
} 

class Bar extends Foo { 
    protected function __construct() { 
    } 
} 

Khi cố gắng để thực thi mã đó, tôi nhận được một lỗi nghiêm trọng: "PHP Fatal error: Trình độ tiếp cận Bar :: __ construct() phải được công khai (như trong lớp Foo) trong/home/berry/foo.php trên dòng 12. " Điều đó có nghĩa là bạn không thể thay đổi cấp truy cập trong một lớp con, nếu cha mẹ đã định nghĩa cấp độ truy cập, điều này thực sự có ý nghĩa rất nhiều: PHP sẽ không biết hàm tạo nào cần gọi, tôi đoán vậy.

Lưu ý: bằng cách xem mã của bạn, B mở rộng A và A sử dụng B. Tại sao chính xác như vậy, nó có vẻ giống như một công trình lạ đối với tôi? Tôi đoán bạn thực sự muốn là composition, not inheritance.

+0

hey Berry, cảm ơn câu trả lời của bạn. Như tôi đã viết trong câu trả lời của mình, tôi cần truy cập các phần tử được bảo vệ trong A và cần B là một singleton. Nhưng nó hơi kỳ lạ trong hành động, b/c của "tình trạng tái cấu trúc" mà tôi đang phải đối mặt. Tôi không chắc chắn nếu đã chọn lựa chọn tốt nhất nhưng nó phải là đơn giản nhất cho bây giờ, tôi nghĩ. – Raffael

+0

Xin chào. Thiết kế này có vẻ kỳ quặc. Bạn cần một lớp cần truy cập vào các phương thức được bảo vệ của một lớp khác (không liên quan?), Sử dụng lớp kia? Có lẽ bạn sẽ được hưởng lợi từ việc giải thích tình hình, xem nếu có điều gì tốt chúng ta có thể nói về nó :) –

+0

Tôi nghĩ rằng nó gây tranh cãi có bao nhiêu ý nghĩa nó làm cho PHP để hành xử theo cách này (xem https://bugs.php.net/ bug.php? id = 61970). Nhưng lý do chính thức được đưa ra cho điều này là Nguyên tắc thay thế Liskov, mà về cơ bản nói rằng các trường hợp của các lớp dẫn xuất nên "phù hợp" trong đó một cá thể lớp cơ sở được mong đợi. – Peter

6

Bạn có thể xác định hàm tạo như được bảo vệ hoặc riêng tư. Đây đang biên dịchruns just fine since OOP was rewritten for PHP/5:

<?php 

class A{ 
    public function __construct(){ 
     echo 'Instance of A created' . PHP_EOL; 
    } 
} 

class B{ 
    protected function __construct(){ 
     echo 'Instance of B created' . PHP_EOL; 
    } 
} 

class C{ 
    private function __construct(){ 
     echo 'Instance of C created' . PHP_EOL; 
    } 
} 

Tất nhiên, nhà thầu tư nhân ngăn cản bạn từ việc tạo một thể hiện với từ khóa new, nhưng PHP sẽ kích hoạt một lỗi nghiêm trọng (nó sẽ không chỉ dừng lại chạy):

<?php 

new A; // OK 
new B; // Fatal error: Call to protected B::__construct() from invalid context 
new C; // Fatal error: Call to private C::__construct() from invalid context 
+1

Chỉ cần để có được những điều thẳng: mã đó sẽ không biên dịch tốt. Mã đó sẽ được hiểu là tốt;) –

+1

@Berry Langerak - Tôi * biết * lựa chọn từ của tôi sẽ là chính trị :) –

+0

@ Álvaro G. Vicario: lựa chọn từ của bạn không phải là 'chính trị', nó sai ... :-) – MarcoS

1

bạn có thể tạo khởi tùy chỉnh tĩnh:

<?php 

class FancyClass { 
    public static function init() { 
     new self(); 
    } 

    protected function __construct() { 
     echo 'Instance created!'; 
    } 
} 

# This will not work. 
new FancyClass(); 

# But this will work. 
FancyClass::init(); 
Các vấn đề liên quan