в этом ли смысл замысла Раку?
Справедливо сказать, что Раку не совсем незавершен в этой области. Ваш вопрос затрагивает две темы в дизайне 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 осмысленного поведения, которое скрывает модель состояния, а не думать с точки зрения геттеров / сеттеров, что, как правило, приводит к невозможности совместного размещения данные и поведение, что в любом случае является основной целью ОО.