в этом ли смысл замысла Раку?
Справедливо сказать, что Раку не совсем незавершен в этой области. Ваш вопрос затрагивает две темы в дизайне Raku, которые стоит немного обсудить.
Раку имеет первоклассные l-значения
Раку широко использует l-значения как первоклассную вещь. Когда мы пишем:
has $.x is rw;
Генерируемый метод:
method x() is rw { $!x }
is rwЗдесь указывает на то, что метод возвращающий л-значение - то есть, то , что может быть назначен. Таким образом, когда мы пишем:
$obj.x = 42;
Это не синтаксический сахар: на самом деле это вызов метода, а затем к его результату применяется оператор присваивания. Это работает, потому что вызов метода возвращает Scalarконтейнер атрибута, который затем может быть назначен в. Можно использовать связывание, чтобы разделить это на два шага, чтобы увидеть, что это не тривиальное синтаксическое преобразование. Например, это:
my $target := $obj.x;
$target = 42;
Будет присваивать атрибут объекта. Этот же механизм стоит за многими другими функциями, включая назначение списка. Например, это:
($x, $y) = "foo", "bar";
Работает, Listсоздавая контейнеры $xи$y , , а затем оператор присваивания в этом случае выполняет итерацию каждой стороны попарно, чтобы выполнить присваивание. Это означает, что мы можем использовать средства rwдоступа к объектам там:
($obj.x, $obj.y) = "foo", "bar";
И все это просто естественно работает. Это также механизм назначения для секций массивов и хэшей.
Можно также использовать Proxy для создания контейнера l-значения, где поведение чтения и записи находится под вашим контролем. Таким образом, вы можете положить побочные действия в STORE. Однако...
Раку поощряет семантические методы над «сеттерами»
Когда мы описываем ОО, часто встречаются такие термины, как «инкапсуляция» и «скрытие данных». Ключевая идея здесь заключается в том, что модель состояния внутри объекта, то есть способ представления данных, необходимых для реализации его поведения (методов), может свободно развиваться, например, для обработки новых требований. Чем сложнее объект, тем более освобождающим становится это.
Однако методы получения и установки - это методы, которые неявно связаны с состоянием. Хотя мы можем утверждать, что достигаем сокрытия данных, потому что мы вызываем метод, а не напрямую обращаемся к состоянию, мой опыт показывает, что мы быстро оказываемся в месте, где внешний код выполняет последовательности вызовов установщика для выполнения операции, которая форма особенность зависти анти-шаблон. И если мы делаем это , это довольно уверен , что мы в конечном итоге с логикой снаружи объекта , который делает смесь получения и установки операций для достижения операции. Действительно, эти операции должны были быть представлены как методы с именами, которые описывают то, что достигается. Это становится еще более важным, если мы находимся в параллельной обстановке; хорошо спроектированный объект часто довольно легко защитить на границе метода.
Тем не менее, многие виды использования classдействительно являются типами записей / продуктов: они существуют, чтобы просто сгруппировать кучу элементов данных. Не случайно, что .сигил не только генерирует аксессор, но и:
- Определяет атрибут для установки с помощью логики инициализации объекта по умолчанию (то есть, a
class Point { has $.x; has $.y; }может быть создан как Point.new(x => 1, y => 2)), а также отображает его в .rakuметоде сброса.
- Включает атрибут в
.Captureобъект по умолчанию , что означает, что мы можем использовать его при деструктурировании (например sub translated(Point (:$x, :$y)) { ... }).
Что бы вы хотели, если бы вы писали в более процедурном или функциональном стиле и использовали его classкак средство для определения типа записи.
Дизайн Raku не оптимизирован для умных действий в сеттерах, потому что это плохо для оптимизации. Это выше того, что нужно для типа записи; на некоторых языках мы можем утверждать, что хотим сделать проверку того, что присваивается, но в Raku мы можем обратиться к subsetтипам для этого. В то же время, если мы действительно занимаемся проектированием ОО, нам нужен API осмысленного поведения, которое скрывает модель состояния, а не думать с точки зрения геттеров / сеттеров, что, как правило, приводит к невозможности совместного размещения данные и поведение, что в любом случае является основной целью ОО.