2008-09-17 2 views
1

Ниже приведен пример иерархии классов и кода. То, что я ищу, - это способ определить, вызвал ли у ChildClass1 или ChildClass2 статический метод whoAmI(), не переустанавливая его в каждом дочернем классе.Есть ли способ определить целевой класс в статических методах?

<?php 

abstract class ParentClass { 

    public static function whoAmI() { 

     // NOT correct, always gives 'ParentClass' 
     $class = __CLASS__; 

     // NOT correct, always gives 'ParentClass'. 
     // Also very round-about and likely slow. 
     $trace = debug_backtrace(); 
     $class = $trace[0]['class']; 

     return $class; 
    } 
} 

class ChildClass1 extends ParentClass { 

} 

class ChildClass2 extends ParentClass { 

} 

// Shows 'ParentClass' 
// Want to show 'ChildClass1' 
print ChildClass1::whoAmI(); 
print "\n"; 

// Shows 'ParentClass' 
// Want to show 'ChildClass2' 
print ChildClass2::whoAmI(); 
print "\n"; 

ответ

2

Теперь, когда PHP 5.3 широко доступен в дикой природе, я хотел собрать сводный ответ на этот вопрос, чтобы отразить новые доступные методы.

Как упоминалось в других ответах, PHP 5.3 ввел Late Static Binding через новое ключевое слово static. Также доступна новая функция get_called_class(), которая может использоваться только в методе класса (экземпляре или статическом).

Для определения класса, как было предложено в этом вопросе, функция get_called_class() уместно:

<?php 

abstract class ParentClass { 

    public static function whoAmI() { 
     return get_called_class(); 
    } 

} 

class ChildClass1 extends ParentClass { 

} 

class ChildClass2 extends ParentClass { 

} 

// Shows 'ChildClass1' 
print ChildClass1::whoAmI(); 
print "\n"; 

// Shows 'ChildClass2' 
print ChildClass2::whoAmI(); 
print "\n"; 

user contributed notes for get_called_class() включают несколько реализаций выборок, которые должны работать в PHP 5.2, а также путем использования debug_backtrace().

2

Идентификация класса часто является симптомом непонятного полиморфизма.

Клиентам ChildClass1 и ChildClass2 не нужно различать их.

Нет места, где любой класс должен спрашивать о someObject.whoAmI().

Если у вас есть желание написать if someObject.whoAmI() == 'ChildClass1' { do X(someObject) }, вы действительно должны добавить метод X() в ParentClass с различными реализациями в различных ChildClasses.

Этот тип идентификации типа времени выполнения почти всегда может быть заменен на надлежащие полиморфные конструкции классов.

+0

@ S.Lott Я полностью согласен с тем, что такой метод был бы непрозрачной абстракцией при использовании в реальном коде. В этом случае метод только для того, чтобы обеспечить понятный образец. Моя причина в том, что вы хотите определить дочерний класс, так это то, что я могу использовать методы создания статических экземпляров, которые разделяются всеми членами иерархии классов, но все же вызывают соответствующий дочерний-конструктор. – 2009-09-06 03:54:30

1

Начиная с PHP 5.3 это возможно с использованием static keyword, но пока это невозможно.

Смежные вопросы