นี่เป็นความตั้งใจในการออกแบบของ Raku หรือไม่?
มันยุติธรรมที่จะบอกว่า Raku ไม่ได้ไม่ได้อยู่ในพื้นที่ทั้งหมด คำถามของคุณสัมผัสกับสองธีมในการออกแบบของ Raku ซึ่งทั้งคู่ต่างก็คุ้มค่าที่จะพูดคุยกันเล็กน้อย
Raku มีค่า l ชั้นหนึ่ง
Raku ใช้ประโยชน์จาก l-value อย่างมากมายเป็นสิ่งที่ดีเลิศ เมื่อเราเขียน:
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-value ที่พฤติกรรมการอ่านและการเขียนมันอยู่ภายใต้การควบคุมของคุณ ดังนั้นคุณสามารถใส่การกระทำข้างเคียงลงไปSTORE
ได้ อย่างไรก็ตาม ...
Raku สนับสนุนวิธีการทางความหมายมากกว่า "setters"
เมื่อเราอธิบาย OO คำศัพท์เช่น "encapsulation" และ "data hiding" มักจะเกิดขึ้น แนวคิดหลักในที่นี้คือโมเดลของรัฐภายในวัตถุ - นั่นคือวิธีที่มันเลือกที่จะเป็นตัวแทนของข้อมูลที่ต้องการเพื่อใช้งานพฤติกรรม (วิธีการ) - มีอิสระที่จะพัฒนาตัวอย่างเช่นเพื่อจัดการกับข้อกำหนดใหม่ ยิ่งวัตถุมีความซับซ้อนมากเท่าไหร่ก็ยิ่งมีการปลดปล่อยมากขึ้นเท่านั้น
อย่างไรก็ตาม getters และ setters เป็นวิธีการที่มีการเชื่อมต่อโดยนัยกับรัฐ ในขณะที่เราอาจอ้างว่าเราประสบความสำเร็จในการซ่อนข้อมูลเพราะเราเรียกวิธีการไม่เข้าถึงสถานะโดยตรง แต่ประสบการณ์ของฉันก็คือเราจบลงอย่างรวดเร็วในสถานที่ซึ่งโค้ดภายนอกกำลังทำลำดับของการเรียก setter เพื่อให้ได้การดำเนินการ รูปแบบของคุณสมบัติต่อต้านอิจฉารูปแบบ และถ้าเราทำอย่างนั้นมันค่อนข้างแน่ใจว่าเราจะจบลงด้วยตรรกะนอกวัตถุที่ผสมผสานการดำเนินการของ getter และ setter เพื่อให้ได้การดำเนินการ จริง ๆ แล้วการดำเนินการเหล่านี้ควรได้รับการเปิดเผยเป็นวิธีการที่มีชื่อที่อธิบายถึงสิ่งที่จะทำได้ สิ่งนี้จะสำคัญยิ่งกว่านี้หากเราอยู่ในสภาพพร้อมกัน วัตถุที่ได้รับการออกแบบมาอย่างดีนั้นมักจะง่ายต่อการปกป้องที่ขอบเขตวิธีการ
ที่กล่าวว่าการใช้งานจำนวนมากclass
เป็นประเภทบันทึก / ผลิตภัณฑ์จริง ๆ : พวกมันมีอยู่เพื่อรวมกลุ่มรายการข้อมูลไว้ด้วยกัน มันไม่ใช่อุบัติเหตุที่.
sigil ไม่เพียง แต่สร้าง accessor แต่ยัง:
- เลือกใช้แอตทริบิวต์ที่ถูกตั้งค่าโดยตรรกะการกำหนดค่าเริ่มต้นของวัตถุ (นั่นคือ a
class Point { has $.x; has $.y; }
สามารถสร้างอินสแตนซ์เป็นPoint.new(x => 1, y => 2)
) และแสดงผลใน.raku
วิธีการถ่ายโอนข้อมูล
- เลือกใช้แอตทริบิวต์เป็น
.Capture
วัตถุเริ่มต้นซึ่งหมายความว่าเราสามารถใช้ในการทำลาย (เช่นsub translated(Point (:$x, :$y)) { ... }
)
ซึ่งเป็นสิ่งที่คุณต้องการหากคุณกำลังเขียนในรูปแบบขั้นตอนหรือการทำงานมากขึ้นและใช้class
เป็นวิธีในการกำหนดประเภทบันทึก
การออกแบบ Raku ไม่ได้รับการปรับให้เหมาะสมสำหรับการทำสิ่งที่ฉลาดใน setters เพราะถือว่าเป็นสิ่งที่ไม่ดีสำหรับการปรับให้เหมาะสม มันเกินความจำเป็นสำหรับประเภทบันทึก ในบางภาษาเราอาจโต้แย้งว่าเราต้องการตรวจสอบสิ่งที่ได้รับมอบหมาย แต่ใน Raku เราสามารถเปลี่ยนเป็นsubset
ประเภทนั้นได้ ในเวลาเดียวกันถ้าเราออกแบบ OO จริงๆเราต้องการ API ของพฤติกรรมที่มีความหมายที่ซ่อนโมเดลรัฐแทนที่จะคิดในแง่ของ getters / setters ซึ่งมีแนวโน้มที่จะนำไปสู่ความล้มเหลวในการ colocate ข้อมูลและพฤติกรรมซึ่งเป็นสิ่งสำคัญในการทำ OO อยู่แล้ว