Часто программисту необходимо добавить в класс сеттеры и/или геттеры. Иногда их бывает так много, что добавлять их вручную становится крайне тяжело!
Поэтому сегодня мы будем делать это автоматически с помощью “шаблонной магии”. Но у всякой магии есть ограничения и следует учесть, что поля класса/структуры должны быть строго типизированы.
Вот таким шаблоном можно добиться легкой вставки методов с сеттером и геттером:
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
);
}
}