У меня есть класс вроде:
<?PHP abstract class dbCon { public function OpenConnection() { // Do Something; // On error: $this->ShowError(); } abstract function ShowError(); } class ErrorHandling extends dbCon { public function ShowError() { // Show error } } ?>
В приведенном выше коде есть недостаток. Я хочу вызвать ShowError () из абстрактного класса, но именно там определяется интерфейс. Как бороться с этим?
Вы путаете наследство с делегацией. ErrorHandler действительно должен быть делегатом dbCon.
Одним из полезных способов определить, должен ли класс A быть подкласс B, – спросить себя, если сказать: «A – более конкретный вид, чем B». То есть, имеет ли A по крайней мере все основные атрибуты и поведение B. Пример того, где это верно, а также нет:
ИСТИННО: пума – это тип кошачьих.
В случае 2 грузовик является частью автомобиля, поэтому правильный способ моделировать это по составу; иметь объект Car, который затем может содержать ссылку на объект Trunk.
В случае 3 адвокат является делегатом исполнительного органа звукозаписывающей компании; правильный способ моделирования этого заключается в том, что ваш RLExective объект содержит ссылку на одного или нескольких юристов, которых он знает, и иметь RLExecutive вызов метода SueCollegeStudentOrGrandmother () для любого из Адвокатов, когда возникнет такая необходимость.
В вашей иерархии здесь вы говорите, что ErrorHandler – это тип dbCon. Это не имеет никакого смысла. Было бы более правильным сказать, что ErrorHandler является делегатом dbCon, которому поручено обрабатывать ошибки. В этом случае вам, вероятно, понадобится бесплатный объект ErrorHandler, или, возможно, один с конкретными знаниями о ошибках БД. Всякий раз, когда dbCon получает ошибку, которую он хочет отобразить, он выдает ошибку ErrorHandler с помощью метода ShowError ().
Основываясь на вашем комментарии, кажется, что ваше замешательство заключается в значении расширений . Говоря, что ErrorHandler расширяет dbCon, вы сказали, что ErrorHandler является подклассом dbCon, а не тем, что ErrorHandler добавляет дополнительные функции для dbCon. Это означает, что вам нужно создать экземпляр ErrorHandler, который будет иметь как функциональные возможности dbCon, так и ErrorHandler. Это, вероятно, не то, что вы хотите.
Надеюсь, это имело какой-то смысл.
Вы можете реализовать свой собственный обработчик исключений :
class Exception_Handler extends Exception { ... } class DB_Connection { try { throw new Exception_Handler('Cannot connect to DB: ' . $exception->getMessage() . '.'); } catch (Exception_Handler $exception) { $exception->show(); } }
Подробнее об этом: http://www.w3schools.com/php/php_exception.asp
Я предлагаю вам прочитать о полиморфизме .
Вызов ShowError()
из родительского класса будет определяться классом экземпляра, и это выполняется во время выполнения.
Чтобы продемонстрировать, рассмотрите этот код:
<?PHP abstract class dbCon { public function OpenConnection() { // Do Something; // On error: $this->ShowError(); } abstract function ShowError(); } class ErrorHandling extends dbCon { public function ShowError() { // Show error echo "Error is here\n"; } } class WarningHandling extends dbCon { public function ShowError() { // Show waring echo "Warning is here\n"; } } $ErrorHandling = new ErrorHandling(); $ErrorHandling->OpenConnection(); $WarningHandling = new WarningHandling(); $WarningHandling->OpenConnection(); ?>
При запуске вы получите:
Error is here Warning is here
Зачем?
Потому что первый ShowError()
является объектом типа ErrorHandling
. PHP видит, что объект имеет конкретный тип ErrorHandling
поэтому, когда ShowError()
вызывается из OpenConnection
, php использует функцию из типа объекта ( ErrorHandling
).
Второй ShowError()
– из объекта WarningHandling
поэтому PHP использует ShowError()
для WarningHandling
.
Внимательно посмотрите на Полиморфизм . Полиморфизм является одним из наиболее важных понятий ООП (так как он отсутствует только для объектно-ориентированных).
Надеюсь это поможет.