스몰 토크에서 클래스 변수는 어디에 정의되어 있습니까?
예를 들어 class에 대한 새 클래스 변수를 MyClass
정의하면 정의가 in MyClass
또는 in MyClass class
? 않음 MyClass class
에도 새로운 클래스 변수에 대해 알고?
답변
예, 클래스 변수는 클래스 및 메타 클래스와 공유됩니다. 또한 모든 서브 클래스 (및 해당 메타 클래스)와 공유됩니다. 클래스 변수는 일반적으로 클래스보다 더 넓은 범위에서 공유된다는 아이디어를 더 잘 전달하기 위해 대문자로 표시됩니다. 클래스에서 클래스 변수를 정의합니다 (메타 클래스가 아님).
클래스 변수는 메타 클래스 수준에서 정의 된 인스턴스 변수 인 클래스 인스턴스 변수, 즉 클래스 객체의 인스턴스 변수와 혼동되어서는 안됩니다. 이 개념은 단순함에도 불구하고 (또는 그 때문에) 다소 모호합니다. 인스턴스 변수는 인스턴스의 모양 (슬롯)을 정의하기 위해 항상 클래스에서 정의 됩니다. 따라서이 정의를 클래스의 클래스 인 메타 클래스에 적용하면 여기에 정의 된 인스턴스 변수가 인스턴스의 모양을 정의하며 일반적으로 클래스는 하나뿐입니다.
클래스 변수로 돌아가서 클래스 (inst 측)에서 정의하고 메타 클래스 (즉, 클래스 측)에서 초기화합니다. 이들은 인스턴스, 서브 인스턴스, 서브 클래스 및 메타 클래스간에 공유되는 의미에서 (부분) 글로벌이므로 우리가 글로벌을 취급하는 일반적인주의를 기울여 처리해야합니다.
한 가지 더 설명
인스턴스 변수가 인스턴스와 서브 인스턴스간에 공유된다고 말할 때, 우리는 그 이름 (및 객체 슬롯의 메모리 위치)을 의미합니다. 우리는 그들의 가치 (상기 슬롯의 내용)를 의미하지 않습니다. 따라서 클래스 C
가 color
ivar를 정의하는 경우 클래스의 두 인스턴스 는 이름을 공유 color
하지만 각 인스턴스의 값은 독립적입니다. 즉, 공유되는 것은 가치가 아니라 이름입니다.
클래스 변수로 공유되는 것은 이름과 값입니다. Association
예를 들어 Theme -> aTheme
공유되는 것은 실제로 객체 입니다. 결과적으로 클래스 변수의 값을 수정하면 모든 참조에 영향을줍니다. 클래스 인스턴스 변수는 일반 인스턴스와 하위 인스턴스가 아니라 클래스와 하위 클래스를 형성한다는 점을 제외하면 인스턴스 변수 일 뿐이므로 클래스 인스턴스 변수의 경우에는 해당되지 않습니다.
Smalltalk 변수에 대한 자세한 내용은 https://stackoverflow.com/a/42460583/4081336
Leandro의 답변을 보완하는 것처럼 다음은 인스턴스 측 (클래스)과 클래스 측 (메타 클래스) 간의 클래스 변수 공유를 설명하는 주요 Squeak 구현 특정 메서드입니다.
Metaclass>>classPool
"Answer the dictionary of class variables."
^thisClass classPool
thisClass
Metaclass의 고유 한 인스턴스, 즉 클래스 자체는 어디에 있습니까 ?
그러나 대부분의 스몰 토크 방언에서 유사한 구현을 찾을 가능성이 높습니다.
컴파일러는 먼저 변수를 메서드 / 블록 임시 (methd / block 매개 변수 포함)로 해석 한 다음 인스턴스 변수, 공유 변수로 해석합니다.
classPool 메서드는이 마지막 단계에서 컴파일러에 의해 전송됩니다.
Leandro가 설명했듯이 컴파일러는 인스턴스 변수 슬롯 또는 메서드 임시 변수의 경우 바이트 코드에서 직접 기록되는 오프셋으로 바인딩을 해결하거나 공유 변수의 경우 일종의 연관으로,이 연관은 일반적으로 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로 작성되었습니다!