Имитация наследования нескольких классов

lyxsus

Новичок
Имитация наследования нескольких классов

вот такой код работает. и даже иногда удобен, но есть 2 вопроса. сразу скажу, что предложения с eval уже были.

1) сейчас можно имиторвать наследование только public. это проблема.
2) используется 2 eval'а. а это уже плохо.

если не сложно, присоветуйте чего.

PHP:
<?
abstract class to_import {	//1й класс для импорта
	public $somevar = "sv";

	public function fk($p1, $p2) {
		echo "Imported function called with args p1 = $p1; p2 = $p2<br/>\r\n";
	}
};

abstract class lex {		//2й класс для импорта
	public $nick = "Lyxsus";

	public function wau() {
		echo "My name is \"" . $this->nick . "\"!\r\n<br/>";
	}
}


class base {		//базовый класс
	protected $__classes = Array();

	public function __call($a, $b) {	//отсутствующие методы ищем в подгруженных классах

		foreach($this->__classes as $class_name) {	//листинг классов
			$cm = get_class_methods($class_name);

			if(in_array($a, $cm)) {	//ищем, нету ли в классе нужного метода
				$params = "";
				if(is_array($b)) {	//генерим строчку с парамами
					foreach($b as $param) {
						$params .= $param . ",";
					}
					$params = substr($params, 0, strlen($params) - 1);
				}

				eval('return ' . $class_name . '::' . $a . '(' . $params . ');');	//от eval'а хотелось бы избавиться
			}
		}

	}

	protected function __implement($class_name) {	//подключение класса
		$this->__classes[sizeof($this->__classes)] = $class_name;	//имя класса запоминаем

		//дописываем переменные
		$vars = get_class_vars($class_name);
		foreach($vars as $var => $val) {
			eval('$this->' . $var . ' = \'' . $val . '\';');	//и от этого eval'а тоже.
		}
	}
};

class go extends base {

	function __construct() {
		$this->__implement("to_import");
		$this->__implement("lex");
	}

	function t() {
		$this->fk(4, 6);
		echo "Own function.<br/>\r\n";
	}
};


//тестим
$g = new go;
$g->fk(2, 4);
$g->t();

$g->wau();
$g->nick = "Nick";
$g->wau();


?>
-~{}~ 13.04.05 13:59:

поправка. в "__call", там, где параметры генеряться надо заменить фуыч на

PHP:
					for($i = 0; $i < sizeof($b); $i++) {
						$param = $b[$i];
						$params .= '&$b[' . $i . ']';
						if($i != sizeof($b)-1)
							$params .= ", ";
					}
 

crocodile2u

http://vbolshov.org.ru
ИМХО, бесполезная конструкция. Понятность кода пропадает напрочь. Вдобавок, "чужие" методы вызываются только статически.
От eval, конечно, можно избавиться:
call_user_func()
call_user_func_array()
 

lyxsus

Новичок
call_user_func не прокатит.
если вызвать метод класса через "class_name::func_name()", то вызов происходит из контекста класса. т.е. обращаясь из вызываемой ф-ии к $this, мы получаем указатель на текущий класс, что нам и надо. с call_user_func так не получается :(
 

crocodile2u

http://vbolshov.org.ru
Вообще-то, если вызвать метод класса статически, т е. "class_name::func_name()", то мы теряем всякую возможность использовать переменную $this.

-~{}~ 13.04.05 18:05:

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

-~{}~ 13.04.05 18:06:

Единственно вот еще - почитай-таки мануал по call_user_func() и
call_user_func_array()
 

lyxsus

Новичок
ты код хоть запускал? вот теперь запусти и еще раз глядя мне в глаза скажи, что $this не вызывается.
 

crocodile2u

http://vbolshov.org.ru
>>> $this не вызывается <<<

Да, действительно, в данном случае я поначалу недосмотрел, будет доступна переменная $this.

От этого код не становится полезнее, или хотя бы понятнее.

Вот тебе две ситуации, в которых он окажет тебе медвежью услугу:

1) Пересечение имен переменных.
2) Пересечение имен методов.

И к тому же - на ЛЮБОЙ вызов ЛЮБОГО метода такого класса будет произодиться несколько вызовов методов, которые на самом деле не нужны.
 

lyxsus

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

crocodile2u

http://vbolshov.org.ru
Сам-то как думаешь? Возможно это при твоем _неструктуризированном_ подходе?
 

Screjet

Новичок
Неплохо. Только нехватает возможности родителям работать с потомком.
 

crocodile2u

http://vbolshov.org.ru
Да где неплохо-то?
Конструкторов - нет.
Конфликты имен - неизбежны.
Работаешь с каким-либо свойством, и _не_ знаешь, какому объекту оно принадлежит. Да и самих объектов-то не создается.
Мало-мальски объемная система, реализованная с таким подходом, сама запутает своего собственного разработчика. Короче - это чудовище Франкенштейна. имхо.
 

crocodile2u

http://vbolshov.org.ru
Есс, что будет коряво изначально...
А потом - будет замечательно? Сам _подход_ не даст такой схеме стать сколько-нибудь полезной. Что это вообще такое - вызывать метод, и не знать, какой класс его предоставил. В нынешней реализации, если встретятся у нескольких классов методы с одинаковыми названиями, выпонятся _все_! Это - нормально? По-моему, нет. То же - со свойствами. Вдобавок, такой пример:

У меня есть класс Автор, и класс Книга. Интерфейс - инсерт, апдейт, делит, селект. И мне _хорошо_ от того, что я могу создать экземпляры этих классов, и работать с ними.

В предлагаемом подходе откуда возьмутся эти экземпляры? методы ВООБЩЕ перемешаются напрочь. Идеологически неправлиьный подход, и права на жизнь, имхо, не имеющий.
 

lyxsus

Новичок
смысл вот в чем.

у нас, допустим, есть двигло. есть модуль-класс. в самом классе описаны необходимые ф-ии для реальзации логики. и есть у нас два режима работы: клиентский и админский. по определению они очень здоровые. найти что-то сложно. этот монстр позволил разделить это на отдельные классы и подключать только необходимые. причем практически все методы были перенесены баныльным copy/paste без изфращений. возникло только 2 бага:
1) private
2) надо было перегрузить ф-ю род. класса, но с этим я криво, но справился:
PHP:
<?
/* ... */
	//перегрузим вручную функцию foo
	public function foo() {
		if(class_exists("__pclass"))
			return __pclass::foo();
	}
/* ... */
?>
ЗЫ1: то, что сейчас на форуме было написано минут за 20, не более того.
ЗЫ2: 2 метода вызываться не должно: там return в цикле, в eval'е.
 

Domovoj

Guest
Автор оригинала: lyxsus
смысл вот в чем.

у нас, допустим, есть двигло. есть модуль-класс. в самом классе описаны необходимые ф-ии для реальзации логики. и есть у нас два режима работы: клиентский и админский. по определению они очень здоровые. найти что-то сложно. этот монстр позволил разделить это на отдельные классы и подключать только необходимые. причем практически все методы были перенесены баныльным copy/paste без изфращений. возникло только 2 бага:
1) private
2) надо было перегрузить ф-ю род. класса, но с этим я криво, но справился:
PHP:
<?
/* ... */
	//перегрузим вручную функцию foo
	public function foo() {
		if(class_exists("__pclass"))
			return __pclass::foo();
	}
/* ... */
?>
ЗЫ1: то, что сейчас на форуме было написано минут за 20, не более того.
ЗЫ2: 2 метода вызываться не должно: там return в цикле, в eval'е.
Почитай про шаблон проектирования Decorator. Здаётся мне, что именно что-то вроде этого ты и пытаешься добиться.
 
Сверху