#Private attribute example
class C {
has $!w; #private attribute
multi method w { $!w } #getter method
multi method w ( $_ ) { #setter method
warn “Don’t go changing my w!”; #some side action
$!w = $_
}
}
my $c = C.new
$c.w( 42 )
say $c.w #prints 42
$c.w: 43
say $c.w #prints 43
#but not
$c.w = 44
Cannot modify an immutable Int (43)
sejauh ini, sangat masuk akal, dan kemudian
#Public attribute example
class C {
has $.v is rw #public attribute with automatic accessors
}
my $c = C.new
$c.v = 42
say $c.v #prints 42
#but not
$c.v( 43 ) #or $c.v: 43
Too many positionals passed; expected 1 argument but got 2
Saya menyukai kedekatan penugasan '=', tetapi saya membutuhkan kemudahan untuk melakukan tindakan sampingan yang disediakan oleh berbagai metode. Saya mengerti bahwa ini adalah dua dunia yang berbeda, dan mereka tidak bercampur.
TETAPI - Saya tidak mengerti mengapa saya tidak bisa hanya pergi $ cv (43) Untuk mengatur atribut publik
- Saya merasa bahwa raku membimbing saya untuk tidak mencampur dua mode ini - beberapa atribut pribadi dan beberapa publik dan bahwa tekanannya adalah pada metode metode (dengan beberapa: gula dari usus besar) - apakah ini maksud dari desain Raku?
- Apakah saya melewatkan sesuatu?
is rw
ditentukan. Mengembalikan Proxy tidak akan mengubah jumlah parameter yang diijinkan pada accessor.= foo
dan.(foo)
untuk pengaturan) dan mengaktifkan efek samping yang harus dilakukan dalam kedua kasus (tetapi tidak ketika hanya diambil): tio.run/…Jawaban:
Wajar untuk mengatakan bahwa Raku tidak sepenuhnya tidak terbuka di bidang ini. Pertanyaan Anda menyentuh dua tema dalam desain Raku, yang sama-sama layak untuk dibahas.
Raku memiliki nilai l kelas satu
Raku memanfaatkan banyak nilai-l sebagai hal kelas satu. Ketika kita menulis:
Metode yang dihasilkan adalah:
Di
is rw
sini menunjukkan bahwa metode mengembalikan nilai-l - yaitu, sesuatu yang dapat ditugaskan. Demikian ketika kita menulis:Ini bukan gula sintaksis: itu benar-benar panggilan metode, dan kemudian operator penugasan diterapkan untuk hasilnya. Ini berhasil, karena pemanggilan metode mengembalikan
Scalar
wadah atribut, yang kemudian dapat ditugaskan ke. Seseorang dapat menggunakan binding untuk membagi ini menjadi dua langkah, untuk melihat itu bukan transformasi sintaksis sepele. Sebagai contoh, ini:Akan menugaskan ke atribut objek. Mekanisme yang sama ini ada di balik berbagai fitur lain, termasuk penugasan daftar. Sebagai contoh, ini:
Bekerja dengan membangun
List
wadah berisi$x
dan$y
, dan kemudian operator penugasan dalam hal ini iterates setiap sisi berpasangan untuk melakukan penugasan. Ini berarti kita dapat menggunakanrw
pengakses objek di sana:Dan itu semua secara alami bekerja. Ini juga merupakan mekanisme di balik penugasan pada irisan array dan hash.
Satu juga dapat digunakan
Proxy
untuk membuat wadah bernilai-l di mana perilaku membaca dan menulis itu di bawah kendali Anda. Dengan demikian, Anda bisa memasukkan aksi samping ke dalamSTORE
. Namun...Raku mendorong metode semantik atas "setter"
Ketika kami menggambarkan OO, istilah seperti "enkapsulasi" dan "menyembunyikan data" sering muncul. Gagasan utama di sini adalah bahwa model keadaan di dalam objek - yaitu, cara yang dipilihnya untuk merepresentasikan data yang diperlukan untuk mengimplementasikan perilakunya (metode) - bebas untuk berevolusi, misalnya untuk menangani persyaratan baru. Semakin kompleks objek, semakin membebaskan ini menjadi.
Namun, getter dan setter adalah metode yang memiliki koneksi implisit dengan negara. Meskipun kami mungkin mengklaim bahwa kami mencapai penyembunyian data karena kami memanggil metode, tidak mengakses keadaan secara langsung, pengalaman saya adalah bahwa kami dengan cepat berakhir di tempat di mana kode luar membuat urutan panggilan setter untuk mencapai operasi - yang merupakan suatu bentuk iri fitur anti-pola. Dan jika kita melakukan itu , cukup yakin kita akan berakhir dengan logika di luar objek yang melakukan campuran antara pengambil dan penyetel operasi untuk mencapai operasi. Sungguh, operasi ini seharusnya diekspos sebagai metode dengan nama yang menggambarkan apa yang sedang dicapai. Ini menjadi lebih penting jika kita berada dalam pengaturan bersamaan; objek yang dirancang dengan baik seringkali cukup mudah untuk dilindungi pada batas metode.
Yang mengatakan, banyak penggunaan
class
benar-benar jenis catatan / produk: mereka ada untuk hanya mengelompokkan sekelompok item data. Bukan kebetulan bahwa.
sigil tidak hanya menghasilkan accessor, tetapi juga:class Point { has $.x; has $.y; }
dapat dipakai sebagaiPoint.new(x => 1, y => 2)
), dan juga menjadikannya dalam.raku
metode dumping..Capture
objek default , yang berarti kita dapat menggunakannya dalam merusak (misalnyasub translated(Point (:$x, :$y)) { ... }
).Mana hal-hal yang Anda inginkan jika Anda menulis dengan gaya yang lebih prosedural atau fungsional dan menggunakan
class
sebagai sarana untuk menentukan jenis rekaman.Desain Raku tidak dioptimalkan untuk melakukan hal-hal pintar di setter, karena itu dianggap hal yang buruk untuk dioptimalkan. Ini melampaui apa yang diperlukan untuk tipe rekaman; dalam beberapa bahasa kita bisa berdebat kita ingin melakukan validasi dari apa yang ditugaskan, tetapi di Raku kita dapat beralih ke
subset
tipe untuk itu. Pada saat yang sama, jika kita benar-benar melakukan desain OO, maka kita menginginkan API perilaku yang berarti yang menyembunyikan model negara bagian, daripada berpikir dalam kaitannya dengan pengambil / penentu, yang cenderung mengarah pada kegagalan untuk berkolokasi. data dan perilaku, yang merupakan inti dari melakukan OO.sumber
Proxy
s (meskipun saya menyarankan itu ha). Satu-satunya waktu saya menemukan mereka sangat berguna adalah untuk sayaLanguageTag
. Secara internal,$tag.region
mengembalikan objek tipeRegion
(karena disimpan secara internal), tetapi kenyataannya, itu jauh lebih nyaman bagi orang untuk mengatakan$tag.region = "JP"
lebih$tag.region.code = "JP"
. Dan itu benar-benar hanya sementara sampai saya dapat mengekspresikan paksaan dariStr
dalam jenis, misalnya,has Region(Str) $.region is rw
(yang meminta dua fitur yang direncanakan tetapi prioritas rendah terpisah)Nah, itu benar-benar terserah arsitek. Tapi serius, tidak, itu bukan cara standar Raku bekerja.
Sekarang, sangat mungkin untuk membuat
Attribute
sifat dalam ruang modul, sesuatu sepertiis settable
, yang akan membuat metode pengakses alternatif atau yang akan menerima nilai tunggal untuk mengatur nilai. Masalah dengan melakukan ini pada intinya adalah, apakah saya pikir pada dasarnya ada 2 kubu di dunia tentang nilai kembalinya mutator: apakah akan mengembalikan nilai baru , atau nilai lama ?Silakan hubungi saya jika Anda tertarik menerapkan sifat seperti itu dalam ruang modul.
sumber
Saat ini saya curiga Anda baru saja bingung. 1 Sebelum saya menyinggung itu, mari kita mulai lagi dengan apa yang Anda tidak bingung tentang:
Anda dapat melakukan semua hal ini. Artinya Anda menggunakan
=
penugasan, dan banyak metode, dan "langsung saja$c.v( 43 )
", semua pada saat yang sama jika Anda ingin:Kemungkinan sumber kebingungan 1
Di belakang layar,
has $.foo is rw
menghasilkan atribut dan metode tunggal di sepanjang baris:Namun di atas tidak sepenuhnya benar. Mengingat perilaku yang kita lihat,
foo
metode autogenerated kompiler entah bagaimana dideklarasikan sedemikian rupa sehingga setiap metode baru dengan nama yang sama secara diam-diam membayangi itu. 2Jadi, jika Anda menginginkan satu atau beberapa metode khusus dengan nama yang sama dengan atribut, Anda harus melakukannya secara manual mereplikasi metode yang dibuat secara otomatis jika Anda ingin mempertahankan perilaku yang biasanya menjadi tanggung jawabnya.
Catatan kaki
1 Lihat jawaban jnthn untuk penghitungan yang jelas, menyeluruh, otoritatif dari pendapat Raku tentang pengambil / setter pribadi vs publik dan apa yang dilakukannya di belakang layar ketika Anda mendeklarasikan getter / setter publik (yaitu menulis
has $.foo
).2 Jika metode accessor autogenerated untuk atribut dideklarasikan
only
, maka Raku akan, saya kira, melemparkan pengecualian jika metode dengan nama yang sama dideklarasikan. Jika dinyatakanmulti
, maka tidak boleh dibayangi jika metode baru juga dinyatakanmulti
, dan harus membuang pengecualian jika tidak. Jadi accessor autogenerated sedang dideklarasikan dengan tidakonly
atau tidakmulti
melainkan dalam beberapa cara yang memungkinkan bayangan diam.sumber