czy taka jest intencja projektu Raku?
Można śmiało powiedzieć, że Raku nie jest całkowicie pozbawiony ludzi w tej dziedzinie. Twoje pytanie dotyczy dwóch tematów w projekcie Raku, które są warte krótkiej dyskusji.
Raku ma pierwszorzędne wartości l
Raku obficie wykorzystuje wartości l, które są pierwszorzędne. Kiedy piszemy:
has $.x is rw;
Generowana metoda to:
method x() is rw { $!x }
is rw
Tutaj wskazuje, że metoda jest zwrócenie l-wartość - to znaczy, że coś może być przypisany. Kiedy więc piszemy:
$obj.x = 42;
To nie jest cukier składniowy: tak naprawdę jest to wywołanie metody, a następnie do jego wyniku stosuje się operator przypisania. Działa to, ponieważ wywołanie metody zwraca Scalar
kontener atrybutu, do którego można następnie przypisać. Można użyć wiązania, aby podzielić to na dwa kroki, aby przekonać się, że nie jest to trywialna transformacja składniowa. Na przykład:
my $target := $obj.x;
$target = 42;
Byłoby przypisanie do atrybutu obiektu. Ten sam mechanizm kryje się za wieloma innymi funkcjami, w tym przypisywaniem list. Na przykład:
($x, $y) = "foo", "bar";
Polega na konstruowaniu List
zawierające pojemniki $x
i $y
, a następnie operator przypisania w tym przypadku parami iteracje każdym boku do wykonania zadania. Oznacza to, że możemy tam użyć rw
akcesoriów do obiektów:
($obj.x, $obj.y) = "foo", "bar";
I to wszystko po prostu działa naturalnie. Jest to również mechanizm przypisywania do wycinków tablic i skrótów.
Można również użyć Proxy
do utworzenia kontenera o wartości l, w którym zachowanie odczytu i zapisu jest pod twoją kontrolą. W ten sposób możesz umieścić działania poboczne STORE
. Jednak...
Raku zachęca metody semantyczne do „seterów”
Kiedy opisujemy OO, często pojawiają się terminy takie jak „enkapsulacja” i „ukrywanie danych”. Kluczową ideą jest to, że model stanu wewnątrz obiektu - to znaczy sposób, w jaki wybiera on reprezentację danych potrzebnych do wdrożenia swoich zachowań (metod) - może ewoluować, na przykład w celu sprostania nowym wymaganiom. Im bardziej złożony obiekt, tym bardziej staje się on wyzwalający.
Jednak metody pobierające i ustawiające są metodami, które mają niejawne połączenie ze stanem. Chociaż możemy twierdzić, że osiągamy ukrywanie danych, ponieważ wywołujemy metodę, nie uzyskując bezpośredniego dostępu do stanu, z mojego doświadczenia wynika, że szybko kończymy w miejscu, w którym kod zewnętrzny wykonuje sekwencje wywołań ustawiających w celu osiągnięcia operacji - która jest forma anty-wzorca zazdrości funkcji. A jeśli robimy to , to całkiem pewne, będziemy skończyć z logicznego zewnątrz obiektu, który robi mieszankę getter i setter operacji osiągnąć operację. Naprawdę, operacje te powinny były zostać ujawnione jako metody o nazwach opisujących osiągane cele. Staje się to jeszcze ważniejsze, jeśli jesteśmy w równoległym otoczeniu; dobrze zaprojektowany obiekt jest często dość łatwy do ochrony na granicy metody.
To powiedziawszy, wiele zastosowań class
jest naprawdę typami rekordów / produktów: istnieją po prostu zgrupować kilka elementów danych. To nie przypadek, że .
sigil nie tylko generuje akcesor, ale także:
- Określa, że atrybut jest ustawiany przez domyślną logikę inicjowania obiektu (to znaczy
class Point { has $.x; has $.y; }
można utworzyć instancję jako Point.new(x => 1, y => 2)
), a także renderuje to w .raku
metodzie zrzutu.
- Zamienia atrybut w domyślny
.Capture
obiekt, co oznacza, że możemy go użyć do destrukcji (np sub translated(Point (:$x, :$y)) { ... }
.).
Czego chciałbyś, gdybyś pisał w bardziej proceduralny lub funkcjonalny sposób i używał class
jako środka do zdefiniowania typu rekordu.
Projekt Raku nie jest zoptymalizowany do robienia sprytnych rzeczy w seterach, ponieważ uważa się to za kiepską rzecz do optymalizacji. Wykracza to poza to, co jest potrzebne do typu rekordu; w niektórych językach moglibyśmy argumentować, że chcemy dokonać weryfikacji tego, co zostało przypisane, ale w Raku możemy do tego użyć subset
typów. Jednocześnie, jeśli naprawdę projektujemy OO, to chcemy interfejsu API znaczących zachowań, który ukrywa model stanu, zamiast myśleć w kategoriach pobierających / ustawiających, co zwykle prowadzi do niepowodzenia kolokacji dane i zachowanie, co zresztą w dużej mierze ma sens w OO.