LINUX.ORG.RU

Переопределить метод объекта

 


0

1

Вобщем сабж.

Есть огромный не мой проект.

Мне для использования отладки необходимо в нем изменить метод объекта, причем уже созданного. Созданного потому, что внедрить свой код корректно я могу уже только после его создания. Переопределить метод объекта нельзя - это я знаю. Что можно сделать?

Логичным выглядит какой-то такой путь - создать класс наследник где переопределить метод, потом каким-то чудом скопировать этот уже созданный объект на объект класса наследника. Возникает задача, скопировать объект в объект другого класса. Этот трюк как-то возможно провернуть?

Что еще можно придумать?

★★★★★
Ответ на: комментарий от anonymous

На самом деле у меня есть решение:

class CAllMainSun extends CAllMain { 
		 
		function NeedMethod(
				$arg
			) {
			

			# Вызываем реальную функцию
			$result = parent::NeedMethod(
					$arg
				);
			
			
			return $result;
		}
	}
	
	$TmpOBJ = new CAllMainSun;
	$PropsOBJ = (array)$OBJ;
	
	foreach ($PropsOBJ as $PropName=>$PropValue) {
		$TmpOBJ->$PropName = $PropValue;
	}
	
	unset($OBJ);
	$OBJ = $TmpOBJ;
	unset($TmpOBJ);
Но это же дикий ад какой-то... Нельзя ли это сделать покрасивее?

Suntechnic ★★★★★
() автор топика
Ответ на: комментарий от Suntechnic

1. Что тебе мешает прикрутить нужный тебе сахар?

2. Ну вот выполнил ты redifineClass и в итоге CAllMainSun получил все методы базового класса и возможность их переопределять (т.е. заменять своими с аналогичным названием но другим функционалом). Чем это принципиально отличается от class CAllMainSun extends CAllMain?

boombick ★★★★★
()
Ответ на: комментарий от boombick

Мне конкретно не нравится вот эта конструкция:

foreach ($PropsOBJ as $PropName=>$PropValue) {
		$TmpOBJ->$PropName = $PropValue;
}
Я имел ввиду под redifineClass некоторую функцию которая бы переопределяла класс объекта, заменяя/добавляя методы и добавляя свойства.

Suntechnic ★★★★★
() автор топика

декоратор

anonymous
()
Ответ на: комментарий от Suntechnic

У тебя жуткая каша в голове.

Во-первых:

<?php                                                                                                                                                                                                                                         

class Base {
    public    $prop_one   = 'It is public property';      // Видно извне, можно создать объект и обратиться к свойству, можно переопределить свойство в потомке
    protected $prop_two   = 'It is protected property';  // Видно из потомка, но не видно извне. Можно переопределить в потомке с модификатором public
    private   $prop_three = 'It is private property';     // Приватное свойство, видно только изнутри класса

    public function method_one() {
        echo "Public method!\n"; // Публичный метод, можно создать экземпляр класса и вызвать его, можно переопределить в потомке
    }   

    protected function method_two(){
        echo "Proptected method\n"; // Защищенный метод, можно переопределить в потомке с модификатором public
    }   

    private function method_three(){
        echo "I am private, sorry\n"; // Приватный метод, виден только изнутри объекта
    }   

    public final function stop(){
        echo "Final method\n"; // Публичный метод, но запрещенный к переопределению в потомках
    }   
}

class Child extends Base { // переопределяем ОДИН метод и вообще не трогаем свойства
    public function method_two(){
        echo "Public method now. Hey, parent, how are you?\n";
        parent::method_two();
    }   
}

$obj = new Child;
echo $obj->prop_one . "\n"; // вызываем свойство, определенное в базовом классе и НЕ описанное в наследнике. Никакого явного копирования св-в из базового класса не производилось
$obj->method_two(); // Ну и переопределенный метод дернем

Во-вторых: уясни и четко запомни, что такое инкапсуляция, наследование и полиморфизм в терминах ООП. Разберись как реализована работа с объектами в php

В-третьих, читай про геттеры и сеттеры в частности и про магические методы в целом.

В качестве домашнего задания - подумай как сделать св-ва класса Base редактируемыми, если создан объект класса Base и read-only если к тем же самым св-вам класса Base обращаются из потомка

некоторую функцию которая бы переопределяла класс объекта, заменяя/добавляя методы и добавляя свойства

Опиши логику работы этой функции максимально подробно. Каким образом она должна заменять/добавлять методы и добавлять свойства?

boombick ★★★★★
()
Ответ на: комментарий от boombick

Какой смысл описывать логику функции если ее нет?

Я лучше подробно попытаюсь описать что мне надо. А надо вот что:

В определнный момент выполнения кода, я могу проинклюдится в него. К этому моменту уже создан объект $OBJ. Мне надо перехватить ВСЕ вызовы метода MainMethod которые возникнут после моего инклюда, для целей отладки (банально мне нужен лог вызовов с информацией о параметрах вызова).

Для этого в классе потомке я замещаю его метод на свой, из которого добавляю в глобальный отладочный массив нужную инфу и далее вызываю оригинальный метод. Я не заменя оригинальный метод полностью, так как код должен работать на разных версиях платформы, а он там может отличаться.

Сам класс и механизм подмены объекта я показывал тут: Переопределить метод объекта (комментарий)

Что я там делаю неверно и как это можно улучшить?

Suntechnic ★★★★★
() автор топика
Ответ на: комментарий от Suntechnic
$script_stats = array();
$time = microtime(true);

function track_stats(){
    global $script_stats,$time;
    $trace = debug_backtrace();
    $exe_time = (microtime(true) - $time) * 1000;
    $func_args = implode(", ",$trace[1]["args"]);
    $script_stats[] = array(
        "current_time" => microtime(true),
        "memory" => memory_get_usage(true),
        "file" => $trace[1]["file"].': '.$trace[1]["line"],
        "function" => $trace[1]["function"].'('.$func_args.')',
        "called_by" => $trace[2]["function"].' in '.$trace[2]["file"].': '.$trace[2]["line"],
        "ns" => $exe_time
        );
    $time = microtime(true);
    }

declare(ticks = 1);
register_tick_function("track_stats");
RR
()

Что не позволяет использовать класс — наследник прямо, без извращений? Моя практика говорит, что, обычно, если начинается такая чехарда, то где-то ранее сделана концептуальная ошибка.

KRoN73 ★★★★★
()
Ответ на: комментарий от KRoN73

Не понял? Что значит «использовать класс — наследник прямо»? Сразу создать объект класса-наследника? Не могу. Инклюд моего кода происходит позже чем создается объект.

Концептуальная ошибка? Наверное да - разрабочик не сделал событие на которое я бы мог подцепится в этом месте. Приходится извращаться...

Suntechnic ★★★★★
() автор топика
Ответ на: комментарий от RR

Спасибо, но как раз этого хочется збежать. Слишком много будет тиков...

Suntechnic ★★★★★
() автор топика
Ответ на: комментарий от Suntechnic

Всё равно не представляю ситуацию, когда на PHP нельзя внести мелкую поправку в чужой код.

Если же код строго иммутабелен и все классы инклудятся прямо, то тут ничего уже не поделать. Был в PHP4 сторонний pecl-механизм для рантаймовой модификации классов, но в PHP5 не работает.

KRoN73 ★★★★★
()
Ответ на: комментарий от KRoN73

Нельзя потому что у меня примерно полтора десятка проектов на этой платформе разных версий. Даже допустим я завтра подалбаюсь и поправлю на всех, а послезавтра они дружно обновятся и все мои правки пойдут прахом, потому что файлы эти проапдейтятся с сервера разрабов. Хочется сделать один раз и не трогать больше + легкое подключение на новых проектах.

Suntechnic ★★★★★
() автор топика
Ответ на: комментарий от Suntechnic

Не решить эту проблему нормально без правки исходного кода. А с ней делается элементарно. В простейшем случае тебе нужно только один их класс переименовать.

KRoN73 ★★★★★
()
Ответ на: комментарий от KRoN73

Так то что с ней элементарно это и так понятно :)

Фишка в том, чтобы править только там где это возможно согласно документации. В частности в том инклюде про который я говорю - он не заменяется при обновлениях.

Suntechnic ★★★★★
() автор топика
Ответ на: комментарий от Suntechnic

Концептуальная ошибка? Наверное да - разрабочик не сделал событие на которое я бы мог подцепится в этом месте. Приходится извращаться...

Думаю, что концептуальной ошибки здесь нет. Есть один очень известный язык (легко догадаться, какой), где такая функция прописана в стандарте. Там есть прямая необходимость в функции, потому что язык отличается в высшей степени динамичностью и интерактивностью разработки. Можно менять буквально все во время работы с кодом на живом образе, в том числе, переопределять классы. В таком случае сама интерактивная среда вызывает эту функцию для уже существующих объектов переопределяемого класса.

Полагаю, что в твоем случае такая функция тоже была бы оправдана, хотя в «обычном коде» ею злоупотреблять, конечно, не следовало бы.

dave ★★★★★
()
Ответ на: комментарий от dave

Так в том-то и дело что это не обычный код, а пристегнутый для отладки. Это код отладчика если хотите.

Мне кстати нравится более другой язык - в нем можно менять даже не «буквально все», а вообще все во время работы. А классы там как правило не нужны и при необходимости просто пристегиаваются сбоку. После него меня PHP угнетает... Я не понимаю почему там я могу сделать одной функцией для работы с датами больше чем всем PHP вместе взятым (((

Suntechnic ★★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.