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