Почему не распространен такой оператор?
Это, конечно, ошибочное утверждение.
>> которые, во-первых, работают через reflection и в силу этого имеют ряд недостатков (отсутствие типизации например
Геттеры/сеттеры можно вызывать, например, at compile time.
>> а во-вторых, с ними неудобно работать - я не могу передать куда-то геттер и сеттер как первоклассный объект.
Это тоже ошибочное утверждение. Например, в Java 8 можно
Person p = ...
Lens<String> pNameLens = Lens.of(p::getName, p::setName);
interface Lens<T> {
static <T> Lens<T> of(Supplier<T> getter, Consumer<T> setter) {
return new Lens<> {
public T get { return getter.get; }
public void set(T t) { setter.accept(t); }
};
}
T get;
void set(T t);
}
Линза - обычный объект, для него можно сочинять всякие комбинаторы, например можно написать функциюКакой же это обычный объект, когда он жестко связан со своим прародителем.
template<class C, typename F> struct Lens {
typedef Lens This;
typedef C Class;
typedef F RetVal;
typedef RetVal Class::*Field;
Lens(Field f): f(f) {}
Lens &operator=(Field that) { return f = that, *this; }
RetVal get(Class const &obj) { return obj.*f; }
RetVal set(Class &obj, RetVal const &val) { return obj.*f = val; }
private:
Field f;
};
template<class C, typename F> inline Lens<C, F> lens(F C::*f) { return Lens<C, F>(f); }
#define LENS(field) lens(&field)
struct C { int x; };
C c = {42};
#include <iostream>
{
using namespace std;
cout << LENS(C::x).get(c) << endl;
}
(Можно и ссылку на объект внутри хранить, но лучше расшаренную, а они искаропки только в 11-х плюсах появились.)
я не могу передать куда-то геттер и сеттер как первоклассный объект.я просто делаю на лету из них замыкание. Благо в скале его делать очень просто
methodName _
А если хочется настоящих линз - юзай shapeless и scalaz. Всё типобезопасно и даже без рефлексии.
В C# есть типизированное решение того, что ты хочешь.
Оставить комментарий
luna89
Хочу оператор, который из структуры и поля делает "линзу" - пару из геттера и сеттера. Например, если есть тип:и переменная этого типа:
то
p^name - это линза структуры p в поле name. Она имеет тип:
Оператор нужен для типизированного датабиндинга. Например, в поле ввода для редактирования имени можно передать линзу:
Линза - обычный объект, для него можно сочинять всякие комбинаторы, например можно написать функцию
чтобы потом сделать поле для ввода возраста пользователя:
Из-за отсутствия такого удобного оператора в java появились конвенции о геттерах и сеттерах, которые, во-первых, работают через reflection и в силу этого имеют ряд недостатков (отсутствие типизации например а во-вторых, с ними неудобно работать - я не могу передать куда-то геттер и сеттер как первоклассный объект.
Что печалит, в новых языках, таких как тайпскрипт, тянут идиотские геттеры и сеттеры как в C#.