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