Работа с классами

T. Anre

Новичок
Работа с классами

PHP:
<?php
interface IPHPClass
{
	public function __construct($classname);

	public function export();

	public function newInstance($params = null);

	public function invoke($methodname, $params = null);

	public function getProperty($propertyname);

	public function setProperty($propertyname, $value);

	public function getName();

	public function getMethodNotation($methodname, $notation = '');

	public function getPropertynameNotation($propertyname, $notation = '');

}

class PHPClass implements IPHPClass
{
	private $classname	= '';

	private $Reflection		= null;

	private $Instance		= null;

	public function __construct($classname)
	{
		$this->classname 	= $classname;
		$this->Reflection	= new ReflectionClass($this->classname);
	}

	public function export()
	{
		echo '<pre>';
		ReflectionClass::export($this->classname);
		echo '</pre>';
	}

	public function newInstance($params = null)
	{
		if (is_null($this->Instance))
			$this->Instance = (is_null($params)) ? $this->Reflection->newInstance() : $this->Reflection->newInstance($params);
		return $this->Instance;
	}

	private function createNew($Obj)
	{
		if (is_null($this->Instance))
			if (!$Obj->isPublic() || !$Obj->isStatic())
				throw new PHPClassException('Method or Property ' . $this->classname . '::' . $Obj->getName() . ' is not public or static.');
		else
			if (!$Obj->isPublic())
				throw new PHPClassException('Method or Property ' . $this->classname . '->' . $Obj->getName() . ' is not public.');
		return $Obj;
	}

	public function invoke($methodname, $params = null)
	{
		return $this->createNew(new ReflectionMethod($this->classname, $methodname))->invoke($this->Instance, $params);
	}

	public function getProperty($propertyname)
	{
		return $this->createNew(new ReflectionProperty($this->classname, $propertyname))->getValue($this->Instance);
	}

	public function setProperty($propertyname, $value)
	{
		$this->createNew(new ReflectionProperty($this->classname, $propertyname))->setValue($this->Instance, $value);
	}

	public function getName()
	{
		return $this->classname;
	}

	private function getNotation($str, $tag = '')
	{
	    if (empty($tag))
	        return $str;

	    $matches = array();
	    preg_match('/@'.$tag.'(.*)(\\r\\n|\\r|\\n)/U', $str, $matches);

	    if (isset($matches[1]))
	        return trim($matches[1]);

    	return '';
	}

	public function getMethodNotation($methodname, $notation = '')
	{
		$sDocComment = $this->createNew(new ReflectionMethod($this->classname, $methodname))->getDocComment();
		return $this->getNotation($sDocComment, $notation);
	}

	public function getPropertynameNotation($propertyname, $notation = '')
	{
		$sDocComment = $this->createNew(new ReflectionProperty($this->classname, $propertyname))->getDocComment();
		return $this->getNotation($sDocComment, $notation);
	}

}

class PHPClassException extends Exception
{
	public function __construct($msg)
	{
		parent::__construct($msg);
	}

}


/*
*
* Пример работы класса PHPClass
*
*/

// Non-static
class A
{
	/**
	 * @author T. Anre
	 */
	public function sayHello()
	{
		return 'Non-static, Hello World';
	}

}

// Static
class B
{
	public static function sayHello()
	{
		return 'Static, Hello World';
	}

}

$A = new PHPClass('A');
$A->newInstance();
echo $A->invoke('sayHello') . "\n<br/>";
echo $A->getMethodNotation('sayHello', 'author') . "\n<br/>";

$B = new PHPClass('B');
echo $B->invoke('sayHello') . "\n<br/>";

// Выведет:
// Non-static, Hello World
// T. Anre
// Static, Hello World
?>
Вот небольшой класс для работы с классами :D
Как думаете, что можно доработать?
 

dark-demon

d(^-^)b
тогда колись, зачем так мудрить? :-, почему бы просто не унаследовать все классы от одного?
 

T. Anre

Новичок
Автор оригинала: dark-demon
тогда колись, зачем так мудрить?
Мне изначально не нравился подобный стиль:
PHP:
$classname = 'A';
$Obj = new $classname();
Но появилась 5 версия пыхпыха, с более вменяемым ООП, и теперь можно написать примерно так:
PHP:
$PHPClass = new PHPClass('A');
$Obj = $PHPClass->newInstance();
Автор оригинала: dark-demon
почему бы просто не унаследовать все классы от одного?
Не вижу практического смысла в наследовании всех классов от одного базового(в конец абстрактного). Классы должны быть максимально независимыми и выполнять только одну задачу. Да и к тому же есть статичные классы их, что тоже предлагаете наследовать от одного базового?
 

dark-demon

d(^-^)b
Мне изначально не нравился подобный стиль:
чем?

Не вижу практического смысла в наследовании всех классов от одного базового(в конец абстрактного).
а в чём практический смысл твоих танцев с бубном, кроме "мне нравится писать больше кода, делающего то же самое"

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

HraKK

Мудак
Команда форума
dark-demon
+1

Ненавижу ООП ради ООП. На прошлой работе работал с цмс написаной в этом стиле. Любое изменение - легче застрелиться, чем сделать.
 

T. Anre

Новичок
Да и к тому же есть статичные классы их, что тоже предлагаете наследовать от одного базового?
их я вообще предлагаю не использовать.
Предполагаю, что вы также относитесь и к try...catch :D

з.ы. ИМХО, статичные классы очень полезны.

-~{}~ 03.06.07 22:59:

Автор оригинала: HraKK
dark-demon
+1

Ненавижу ООП ради ООП. На прошлой работе работал с цмс написаной в этом стиле. Любое изменение - легче застрелиться, чем сделать.
ООП - очень полезен, если же работает принцип "тут изменишь, там отвалится", то это не стоит называть "ООП ради ООП", тут скорее всего имеет место закрепощенность, неустойчивость, а также неопределенность системы.

Если ЦМС не реализована на паттернах, то что стоит ожидать от такого кода?
 

С.

Продвинутый новичок
Если ЦМС не реализована на паттернах, то что стоит ожидать от такого кода?
Кажется пора вводить новый диагноз: "Паттерн ради паттерна".
 

С.

Продвинутый новичок
Ненавижу ООП ради ООП. На прошлой работе работал с цмс написаной в этом стиле. Любое изменение - легче застрелиться, чем сделать.
А нам говорят, что классический ООП ведет к более легкой адаптируемости изменчивости системы.
 

cDLEON

Онанист РНРСlub
dark-demon
Например объеденять по функционалу вспомогательные функции полезно статикой.
 

dark-demon

d(^-^)b
QWERTY::anyfunction();
QWERTY_anyfunction();

ты видишь принципиальные различия?

ps: давайте перенесёмся в прошлое, когда ООП ещё не был самоцелью, и впомним для чего понадобились классы? в случаях, когда работа функции зависела от множества переменных, приходилось либо явно передавать ей все переменные, либо позволять ей брать данные самой из внешних источников. первый вариант крайне неудобен, а второй - нарушает принцип инверсии зависимостей и как следствие приводит к монолитности и хрупкости кода. тогда появились так называемые "структуры" - комплексы из различных данных. они позволили передавать сравнительно небольшое число переменных. но это не решило всех проблем. разные данные требовалось по разному инициализировать и уничтожать. при это от того как эти данные были проинициализированны зависит работа других функций, работающих с теми же данными. тогда было введено понятие объекта - структуры данных ассоциированной с некоторым набором функций. так началась эра ООП, где не приходилось помнить какие функции пригодны для обработки каких данный - данные сами знали какие функции умеют с ними работать.
для группировки объектов по типу ввели понятие "класс" в определении которого задавалась структура данных и привязывались нужные функции для работы с ними.
что такое статический класс? это класс без ассоциированных с ним данных. объект этого типа если и можно создать - смысла в этом нет. тобишь это уже и не ООП, ибо нет объектов. это просто набор функций с довольно неудобным вызовом.
классы ради классов...
 

cDLEON

Онанист РНРСlub
Эх китаец, ты китаец...
Я люблю читать красивый код) А нижнее подчёркивание плохо заменто)
 

dark-demon

d(^-^)b
правильнее писать "Эх, китаец ты, китаец..."
а как соотносится красота кода и заметность некоторых функций?
 

T. Anre

Новичок
Автор оригинала: dark-demon
значит тебе не составит труда показать пример увидев который я начну судорожно посыпать голову пеплом? :)
Ну что ж начинай...:D
PHP:
<?php
// з.ы. Код написал специально для dark-demon, при этом код не проверял.
// з.ы. Идея кода основывается на Registry-паттерне,
// который обсуждается в соседней теме, где приседают с синглтонами
final class Registry
{
	private static $store = array();
	
	/**
	 * @return void
	 */
	public static function set($name, $item)
	{
		self::$store[$name] = $item;
	}

	/**
	 * @return void
	 */
	public static function remove($name)
	{
		if (array_key_exists($name, self::$store))
			unset(self::$store[$name]);
	}

	/**
	 * @return mixed
	 */
	public static function get($name)
	{
		if (array_key_exists($name, self::$store))
			return self::$store[$name];
		else
			throw new RegistryException('Item "' . $name . '" is not registred.');
	}

	/**
	 * @return boolean
	 */
	public static function exists($name)
	{
		return array_key_exists($name, self::$store);
	}

	private function __construct()
	{}

	private function __clone()
	{}
}

//Применение


// Где-то там в бездне кода
Registry::set('ExampleObject', new ExampleClass());

// Где-то там бездне кода, только с другой областью видимости
$ExampleObject = Registry::get('ExampleObject');
?>
Хотя думаю кому-то больше понравится такой вот вариант, кстати тоже слету написан. :D
PHP:
<?php
function Registry($action, $name, $value = null)
{
	static $store = array();
	switch ($action) {
		case 'set':
			$store[$name] = $value;
			break;
		case 'get':
			if (array_key_exists($name, $store))
				return $store[$name];
			else
				trigger_error ('Item "' . $name . '" is not registred.', E_USER_ERROR);
			break;
		case 'remove':
			if (array_key_exists($name, $store))
				unset($store[$name]); 
			break;
		case 'exists':
			return array_key_exists($name, $store); 
			break;
		default:
			trigger_error ('Action not found.', E_USER_ERROR);
			break;
	}
}

//Применение


// Где-то там в бездне кода
Registry('set', 'ExampleObject', new ExampleClass());

// Где-то там бездне кода, только с другой областью видимости
$ExampleObject = Registry('get', 'ExampleObject');
 

cDLEON

Онанист РНРСlub
PHP:
class anyClass 
 {
 function anyClass()
   {
   }
 function &obj()
   {
   static $obj;
   if(!isset($obj))
     $obj=new anyClass();
   return $obj;
   }
 function anyMethod($anyVar=false)
  {
  $obj=&anyClass : : obj ();
  //Манипуляция с данными объекта, вызов приватных методов этого объекта и т.д. 
  //Например тогда, когда на весь скрипт используется один экземпляр этого объекта. 
  //Альтернатива глобалам.
  }
 }
 //Вызов
 anyClass:anyMethod(true);
Так что ты говорил там о статике?
 

dark-demon

d(^-^)b
ну ты меня просто без аргументов оставляешь :)
добавлю лишь, что для реестра лучше подходит такой вариант:

Код:
// установка значения
Registry ('ExampleObject', new ExampleClass());

// получение значения
$ExampleObject = Registry ('ExampleObject');

// удаление значения
Registry ('ExampleObject', NULL);

// отдельно от получения значения проверять его наличие не вижу смысла
и то, следует хорошо подумать прежде чем сковывать свои движения реестром!
 

T. Anre

Новичок
Автор оригинала: dark-demon
ps: давайте перенесёмся в прошлое, когда ООП ещё не был самоцелью, и впомним для чего понадобились классы?
Зачем переноситься в прошлое, достаточно посмотреть на классы в matlabe, где один метод - один файл, а класс это папка начинающаяся с @
Эх как мне не хватает нормального ООП в matlab'е. :(

Автор оригинала: dark-demon
что такое статический класс? это класс без ассоциированных с ним данных. объект этого типа если и можно создать - смысла в этом нет. тобишь это уже и не ООП, ибо нет объектов. это просто набор функций с довольно неудобным вызовом.
классы ради классов...
Все-таки, все три кита на которых базируется ООП, соблюдаются, так что не надо говорить, что статики не есть ООП. :D

Вопрос, что значит "класс без ассоциированных с ним данных"?
 
Сверху