це наміри дизайну Раку?
Справедливо сказати, що Раку не є цілком неприхильним у цій галузі. Ваше запитання стосується двох тем дизайну Раку, які обидва варто трохи обговорити.
Раку має першокласні 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справді є типом записів / продуктів: вони існують, щоб просто згрупувати купу елементів. Не випадково .sigil не просто генерує аксесуар, а й:
- Визначає, що атрибут встановлюється за допомогою логіки ініціалізації об'єкта за замовчуванням (тобто, а
class Point { has $.x; has $.y; }може бути ініційований як Point.new(x => 1, y => 2)), а також надає це в .rakuметоді демпінгу.
- Включає атрибут в
.Captureоб'єкт за замовчуванням , тобто ми можемо використовувати його в деструктуризації (наприклад, sub translated(Point (:$x, :$y)) { ... }).
Які речі ви б хотіли, якби ви писали у більш процедурному чи функціональному стилі та використовували classяк засіб визначення типу запису.
Дизайн Raku не оптимізований для виконання розумних речей у сеттерах, тому що це вважається поганою справою для оптимізації. Це понад те, що потрібно для типу запису; на деяких мовах ми можемо стверджувати, що ми хочемо зробити перевірку того, що призначено, але в Раку ми можемо звернутися до subsetтипів для цього. У той же час, якщо ми справді робимо проект OO, тоді ми хочемо API змістовної поведінки, що приховує модель стану, а не думати про терміни / сетери, які, як правило, призводять до невдалої колокації дані та поведінка, що все-таки має сенс робити ОО.