1. <pre>
  2. <?php
  3.  
  4. class S {
  5.  
  6. protected $_data = array();
  7.  
  8. public function __construct($separator) {
  9. $name = get_class($this);
  10. for ($i = 1; $i < 3; $i++) {
  11. for ($j = 1; $j < 3; $j++) {
  12. $this->_data[$i][$j] = sprintf('Property %d%s%d of %s', $i, $separator, $j, $name);
  13. }
  14. }
  15. }
  16.  
  17. public function get($id, $pid) {
  18. return isset($this->_data[$id][$pid]) ? $this->_data[$id][$pid] : null;
  19. }
  20. }
  21.  
  22. class S1 extends S {
  23. }
  24.  
  25. class S2 extends S {
  26. }
  27.  
  28. abstract class A {
  29.  
  30. abstract protected function i();
  31.  
  32. public static function getById($id, $property_id) {
  33. if ($id <= 0 || $property_id <= 0) {
  34. throw new Exception('Неверные данные');
  35. }
  36. return static::i()->get($id, $property_id);
  37. }
  38. }
  39.  
  40. class B extends A {
  41.  
  42. private static $instance;
  43.  
  44. protected function i() {
  45. if (!self::$instance) {
  46. $len = rand(1, 20);
  47. self::$instance = new S1(str_repeat('-', $len));
  48. }
  49. return self::$instance;
  50. }
  51.  
  52. }
  53.  
  54. class C extends A {
  55.  
  56. protected function i() {
  57. $len = rand(1, 20);
  58. return new S2(str_repeat('*', $len));
  59. }
  60.  
  61. }
  62. for ($i = 0; $i < 5; $i++) {
  63. ?>
  64. <div style="border:1px #ccc dashed;"><?php var_dump(B::getById(rand(1,2), rand(1,2))); var_dump(C::getById(rand(1,2), rand(1,2)));?> </div>
  65. <?php
  66. }


If there will be "return self::i()->get($id, $property_id);", you will get

Fatal error: Cannot call abstract method A::i() in /var/web/tests/lsb_2.php on line 37
 
Call Stack:
0.0003 350596 1. {main}() /var/web/tests/lsb_2.php:0
0.0003 350728 2. A::getById() /var/web/tests/lsb_2.php:65