Các biến lớp được định nghĩa ở đâu trong Smalltalk?
Tôi đã tự hỏi, nếu tôi định nghĩa một biến lớp mới, chẳng hạn như cho lớp MyClass
, thì định nghĩa sẽ ở trong MyClass
hay ở trong MyClass class
? Có MyClass class
thậm chí biết về các biến lớp học mới?
Trả lời
Có, các biến lớp được chia sẻ với lớp và siêu kính. Chúng cũng được chia sẻ với tất cả các lớp con (và kính đo của chúng). Một biến lớp thường được viết hoa, để truyền đạt tốt hơn ý tưởng được chia sẻ trong phạm vi rộng hơn lớp. Bạn xác định các biến lớp trong lớp (không phải siêu kính).
Không nên nhầm lẫn các biến lớp với các biến cá thể lớp, là các biến cá thể được định nghĩa ở cấp siêu lớp, tức là các biến cá thể của đối tượng lớp. Khái niệm này hơi tối nghĩa mặc dù nó đơn giản (hoặc vì nó): các biến thể hiện luôn được định nghĩa trong lớp để xác định hình dạng (các vị trí) của các thể hiện của nó . Do đó, nếu chúng ta áp dụng định nghĩa này cho siêu kính, là lớp của lớp, một biến thể hiện được định nghĩa ở đây xác định hình dạng của các thể hiện của nó, trong đó (thường) chỉ có một, là lớp.
Quay lại với các biến lớp, bạn xác định chúng trong lớp (phía inst) và khởi tạo chúng trong siêu kính (tức là phía lớp). Hãy nhớ rằng đây là (một phần) hình cầu theo nghĩa sẽ được chia sẻ giữa các phiên bản, nhóm con, lớp con và kính đo và vì vậy chúng phải được xử lý cẩn thận thông thường mà chúng tôi xử lý hình cầu.
Thêm một điều làm rõ
Khi chúng tôi nói rằng các biến cá thể được chia sẻ giữa các cá thể và phiên bản con, chúng tôi muốn nói đến tên của chúng (và vị trí trong bộ nhớ của các vị trí đối tượng); chúng tôi không có nghĩa là giá trị của chúng (nội dung của các vị trí đã nói). Do đó, hai cá thể của lớp C
sẽ dùng chung tên, chẳng hạn color
, nếu lớp định nghĩa ivar color
, nhưng giá trị của chúng tại mỗi cá thể sẽ độc lập. Nói cách khác, những gì nó được chia sẻ là tên, không phải giá trị.
Với các biến lớp, những gì được chia sẻ là cả tên và giá trị. Nó thực sự là Association
đối tượng, ví dụ Theme -> aTheme
, những gì được chia sẻ. Do đó, bất kỳ sửa đổi nào đối với giá trị của một biến lớp đều ảnh hưởng đến tất cả các tham chiếu của nó. Đây không phải là trường hợp của các biến cá thể của lớp vì chúng không là gì khác ngoài các biến thể hiện, ngoại trừ việc chúng định hình lớp và các lớp con của nó, chứ không phải là các cá thể và phiên bản con thông thường.
Để biết thêm thông tin về các biến Smalltalk, hãy xem https://stackoverflow.com/a/42460583/4081336
Cũng giống như một phần bổ sung cho câu trả lời của Leandro, đây là phương thức triển khai Squeak chính cụ thể giải thích việc chia sẻ các biến lớp giữa phía cá thể (lớp) và phía lớp (siêu kính):
Metaclass>>classPool
"Answer the dictionary of class variables."
^thisClass classPool
đâu thisClass
là phiên bản duy nhất của Metaclass, đó chính là lớp ...
Mặc dù vậy, có rất nhiều cơ hội để tìm thấy cách triển khai tương tự trong hầu hết các phương ngữ Smalltalk.
Trước tiên, trình biên dịch sẽ cố gắng giải quyết biến dưới dạng một phương thức / khối tạm thời (bao gồm các tham số methd / khối), sau đó là các biến thể hiện, sau đó là các biến được chia sẻ.
Phương thức classPool được gửi bởi trình biên dịch trong giai đoạn cuối cùng này.
Leandro đã giải thích rằng, trình biên dịch hoặc giải quyết ràng buộc chỉ như một phần bù sẽ được phiên mã trực tiếp trong bytecode trong trường hợp vị trí biến cá thể hoặc biến tạm thời của phương thức, hoặc như một loại Liên kết cho trường hợp biến được chia sẻ, liên kết này nói chung được thêm vào các ký tự CompiledMethod và được chia sẻ hiệu quả giữa tất cả các phương thức xử lý biến này (tất cả các phương thức đều trỏ đến cùng một đối tượng PGS được chia sẻ hiệu quả).
Phần trình biên dịch cụ thể hơn nhiều về phương ngữ, trong Squeak, đó là phương pháp này được sử dụng để giải quyết ràng buộc của các biến được chia sẻ:
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
Điều này muốn nhắc bạn rằng một trong những phần thú vị nhất của Smalltalk là bạn có thể đào sâu vào việc triển khai từ bên trong IDE, về cơ bản Smalltalk được viết bằng Smalltalk!