Добавление в класс универсального свойства

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

Осуществить подобную «махинацию» можно с помощью следующего шаблона:

template addTypedGetter(string propertyVariableName, string propertyName)
{
	import std.string : format;

	const char[] addTypedGetter = format(
		`
		@property
		{
			T %2$s(T)() const
			{
				alias typeof(return) returnType;
				return cast(returnType) %1$s;
			}
		}`,
		propertyVariableName,
		propertyName
		);
}

Шаблон addTypedGetter предполагает наличие некоторой внутренней переменной, в которой и храниться значение интересующего нас свойства. addTypedGetter принимает два аргумента: propertyVariableName — имя внутренней переменной со значением свойства и propertyName — имя геттера (т.е. имя процедуры, с помощью которой будет производиться получение значения свойства). Чтобы применить шаблон нужно просто его «подмешать» в определение нужного класса, добавив внутрь класса подобие следующего:

// красная компонента цвета
mixin(addTypedGetter!("R", "red"));

Эта строка добавит свойство red в класс, а получить значение нужного типа можно так:

<переменная класса>.red!float;

то есть, просто указав нужный тип после восклицательного знака.

Естественно, у addTypedGetter есть ограничения: данный шаблон работает только со встроенными типами или такими, у которых определен метод opCast, учитывающий преобразование типа данных, определенного пользователем, в нужный тип. Но даже несмотря на такое жесткое ограничение, приведенный шаблон является очень мощным инструментом и может служить основой для создания более гибких и универсальных шаблонов.

Добавить комментарий