Автоматическое добавление сеттеров и геттеров

Часто программисту необходимо добавить в класс сеттеры и/или геттеры. Иногда их бывает так много, что добавлять их вручную становится крайне тяжело!

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

Вот таким шаблоном можно добиться легкой вставки методов с сеттером и геттером:

import std.stdio;
import std.string;

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

	const char[] addProperty = format(
		`
		private %2$s %1$s;

		void set%3$s(%2$s %1$s)
		{
			this.%1$s = %1$s;
		}

		%2$s get%3$s()
		{
			return %1$s;
		}
		`,
		propertyVariableName,
		variableType,
		propertyName
		);
}

В качестве аргументов используются имя поля, строка с описанием его типа и именем метода, а в ответ будут сгенерированы сеттер с именем set<имя_свойства> и геттер с именем get<имя_свойства>.

Небольшая демонстрация (любезно предоставленная Bagomot‘ом):

struct Product
{
	mixin(addProperty!("id", "int", "ID"));
	mixin(addProperty!("uid", "string", "UID"));
	mixin(addProperty!("pseudoname", "string", "Pseudoname"));
	mixin(addProperty!("name", "string", "Name"));
	mixin(addProperty!("imagePath", "string", "Image"));
	mixin(addProperty!("category", "int", "Category"));
	mixin(addProperty!("cost", "float", "Cost"));

	string toString()
	{
		return format("%d;%s;%s;%s;%s;%d;%0.2f;",
			id,
			uid,
			pseudoname,
			name,
			imagePath,
			category,
			cost
		);
	}
}

void main()
{
	import std.stdio;

	Product product;

	product.setID(1);
	product.setUID("12:0");
	product.setPseudoname("minecraft:coal");
	product.setName("Coal");
	product.setImage(`/shop/minecraft_coal_0.png`);
	product.setCategory(3);
	product.setCost(0.05);

	writeln(product);
}

Также можно нашу разработку немного модифицировать таким образом, чтобы она принимала не строку с описанием типа, а сам тип (для этого используется свойство .stringof любого типа):

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

	const char[] addProperty = format(
		`
		private %2$s %1$s;

		void set%3$s(%2$s %1$s)
		{
			this.%1$s = %1$s;
		}

		%2$s get%3$s()
		{
			return %1$s;
		}
		`,
		propertyVariableName,
		T.stringof,
		propertyName
		);
}

struct Product
{
	mixin(addProperty!(int, "id", "ID"));
	mixin(addProperty!(string, "uid", "UID"));
	mixin(addProperty!(string, "pseudoname", "Pseudoname"));
	mixin(addProperty!(string, "name", "Name"));
	mixin(addProperty!(string, "imagePath", "Image"));
	mixin(addProperty!(int, "category", "Category"));
	mixin(addProperty!(float, "cost", "Cost"));

	string toString()
	{
		return format("%d;%s;%s;%s;%s;%d;%0.2f;",
			id,
			uid,
			pseudoname,
			name,
			imagePath,
			category,
			cost
		);
	}
}

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