ตัวแปรคลาสกำหนดไว้ที่ไหนใน Smalltalk?

Jan 19 2021

ฉันสงสัยว่าถ้าฉันกำหนดตัวแปรคลาสใหม่เช่นสำหรับคลาสMyClassนิยามจะอยู่ในMyClassหรือในMyClass class? ไม่MyClass classทราบเกี่ยวกับตัวแปรคลาสใหม่หรือไม่?

คำตอบ

5 LeandroCaniglia Jan 20 2021 at 00:36

ใช่ตัวแปรคลาสจะแชร์กับคลาสและเมตาคลาส นอกจากนี้ยังแชร์กับคลาสย่อยทั้งหมด (และเมตาคลาส) โดยปกติตัวแปรคลาสจะเป็นตัวพิมพ์ใหญ่เพื่อถ่ายทอดความคิดที่ดีกว่าในการแชร์ในขอบเขตที่กว้างกว่าคลาส คุณกำหนดตัวแปรคลาสในคลาส (ไม่ใช่เมตาคลาส)

ไม่ควรสับสนตัวแปรคลาสกับตัวแปรอินสแตนซ์คลาสซึ่งเป็นตัวแปรอินสแตนซ์ที่กำหนดในระดับเมตาคลาสเช่นตัวแปรอินสแตนซ์ของคลาสออบเจ็กต์ ความคิดนี้ค่อนข้างชัดเจนแม้จะมีความเรียบง่าย (หรือเพราะมัน): ตัวแปรเช่นมีการกำหนดไว้เสมอในชั้นเรียนเพื่อกำหนดรูปร่าง (สล็อต) กรณีของตน ดังนั้นหากเราใช้นิยามนี้กับ metaclass ซึ่งเป็นคลาสของคลาสตัวแปรอินสแตนซ์ที่กำหนดไว้ที่นี่จะกำหนดรูปร่างของอินสแตนซ์ซึ่งโดยปกติจะมีคลาสเดียว

กลับไปที่ตัวแปรคลาสคุณกำหนดไว้ในคลาส (ฝั่ง inst) และเริ่มต้นใน metaclass (เช่นฝั่งคลาส) โปรดจำไว้ว่าสิ่งเหล่านี้คือลูกโลก (บางส่วน) ในความหมายที่จะใช้ร่วมกันระหว่างอินสแตนซ์สารกลุ่มย่อยและเมตาคลาสดังนั้นจึงต้องจัดการด้วยความระมัดระวังตามปกติที่เราปฏิบัติต่อโลก


อีกหนึ่งคำชี้แจง

เมื่อเรากล่าวว่าตัวแปรอินสแตนซ์ถูกใช้ร่วมกันระหว่างอินสแตนซ์และสสารเราหมายถึงชื่อของมัน (และตำแหน่งในหน่วยความจำของช่องอ็อบเจ็กต์) เราไม่ได้หมายถึงค่าของพวกเขา (เนื้อหาของสล็อตดังกล่าว) ดังนั้นสองอินสแตนซ์ของคลาสCจะใช้ชื่อร่วมกันcolorเช่นถ้าคลาสกำหนด ivar colorแต่ค่าของมันในแต่ละอินสแตนซ์จะเป็นอิสระ กล่าวอีกนัยหนึ่งสิ่งที่แชร์คือชื่อไม่ใช่ค่า

ด้วยตัวแปรคลาสสิ่งที่ใช้ร่วมกันคือทั้งชื่อและค่า จริงๆแล้วมันคือAssociationวัตถุตัวอย่างเช่นTheme -> aThemeสิ่งที่แชร์ ดังนั้นการปรับเปลี่ยนค่าของตัวแปรคลาสจะมีผลต่อการอ้างอิงทั้งหมด นี่ไม่ใช่กรณีของตัวแปรอินสแตนซ์คลาสเนื่องจากไม่ใช่ตัวแปรอินสแตนซ์ยกเว้นว่าจะกำหนดคลาสและคลาสย่อยแทนที่จะเป็นอินสแตนซ์และสสารปกติ


สำหรับข้อมูลเพิ่มเติมเกี่ยวกับตัวแปร Smalltalk โปรดดู https://stackoverflow.com/a/42460583/4081336

2 aka.nice Jan 20 2021 at 23:59

เช่นเดียวกับคำตอบของ Leandro นี่คือวิธีการเฉพาะการใช้งาน Squeak หลักที่อธิบายการแบ่งปันตัวแปรคลาสระหว่างฝั่งอินสแตนซ์ (คลาส) และฝั่งคลาส (เมตาคลาส):

Metaclass>>classPool
    "Answer the dictionary of class variables."

    ^thisClass classPool

ที่thisClassเป็นตัวอย่างที่ไม่ซ้ำกันของ Metaclass ที่เป็นชั้นเอง ...

มีโอกาสสูงที่จะพบการใช้งานที่คล้ายกันในภาษา Smalltalk ส่วนใหญ่

ก่อนอื่นคอมไพเลอร์จะพยายามแก้ไขตัวแปรเป็นวิธีการ / บล็อกชั่วคราว (รวมถึงพารามิเตอร์ methd / บล็อก) จากนั้นตัวแปรอินสแตนซ์จากนั้นตัวแปรที่ใช้ร่วมกัน

เมธอด classPool ถูกส่งโดยคอมไพเลอร์ในระยะสุดท้ายนี้

Leandro ได้อธิบายว่าคอมไพลเลอร์สามารถแก้ไขการผูกได้เช่นเดียวกับออฟเซ็ตที่จะถูกถอดเสียงโดยตรงใน bytecode ในกรณีของช่องตัวแปรอินสแตนซ์หรือตัวแปรวิธีการชั่วคราวหรือเป็นชนิดของการเชื่อมโยงสำหรับกรณีตัวแปรที่ใช้ร่วมกันการเชื่อมโยงนี้โดยทั่วไป เพิ่มเข้าไปในตัวอักษร CompiledMethod และใช้ร่วมกันอย่างมีประสิทธิภาพระหว่างวิธีการทั้งหมดที่จัดการกับตัวแปรนี้ (วิธีการทั้งหมดชี้ไปที่วัตถุ Assocation เดียวกันซึ่งใช้ร่วมกันได้อย่างมีประสิทธิภาพ)

ส่วนของคอมไพเลอร์เป็นภาษาถิ่นที่เฉพาะเจาะจงมากขึ้นใน Squeak ซึ่งเป็นวิธีการนี้ซึ่งใช้สำหรับการแก้ไขการเชื่อมโยงของตัวแปรที่ใช้ร่วมกัน:

class>>bindingOf: varName environment: anEnvironment
    "Answer the binding of some variable resolved in the scope of the receiver"
    | aSymbol binding |
    aSymbol := varName asSymbol.

    "First look in local classVar dictionary."
    binding := self classPool bindingOf: aSymbol.
    binding ifNotNil:[^binding].

    "Next look in local shared pools."
    self sharedPools do:[:pool | 
        binding := pool bindingOf: aSymbol.
        binding ifNotNil:[^binding].
    ].

    "Next look into superclass pools"
    superclass ifNotNil: [^ superclass bindingOf: aSymbol environment: anEnvironment].

    "No more superclass... Last look in declared environment."
    ^anEnvironment bindingOf: aSymbol

นี่คือการเตือนให้คุณทราบว่าส่วนที่น่าสนใจที่สุดอย่างหนึ่งของ Smalltalk คือคุณสามารถเจาะลึกการใช้งานได้จากภายใน IDE โดย Smalltalk จะเขียนใน Smalltalk เป็นหลัก!