클래스 변수

클래스 변수 (Class variables)

클래스 변수는 인스턴스가 아니라 클래스에 묶여 있어요. at 기호가 두 개(@@) 붙는 게 특징입니다. 예시를 볼게요:

class Counter
  @@instances = 0

  def initialize
    @@instances += 1
  end

  def self.instances
    @@instances
  end
end

Counter.instances # => 0
Counter.new
Counter.new
Counter.new
Counter.instances # => 3

클래스 변수는 클래스 메서드나 인스턴스 메서드 양쪽에서 읽고 쓸 수 있어요.

기본값과 함께 초기화되면, 타입 추론 알고리즘이 변수의 타입을 대부분 암묵적으로 알아낼 수 있습니다:

module InferredTypes
  @@integer = 1 # : Int32
  @@string = "" # : String
end

다만 메서드 호출이 들어간 복잡한 표현식 같은 경우는 타입을 추론하지 못해요. 그런 경우엔 변수 타입을 명시적으로 지정해 주어야 합니다:

def generate_foo
  1
end

module NonInferableType
  @@untyped = generate_foo() # Error: can't infer the type of class variable '@@foo' of NonInferableTypes
  @@typed : Int32 = generate_foo()
end

클래스 변수는 서브클래스에 상속되는데, 의미상 타입은 같지만 각 클래스마다 런타임 값이 다릅니다. 예시로 볼게요:

class Parent
  @@numbers = [] of Int32

  def self.numbers
    @@numbers
  end
end

class Child < Parent
end

Parent.numbers # => []
Child.numbers  # => []

Parent.numbers << 1
Parent.numbers # => [1]
Child.numbers  # => []

클래스 변수는 모듈과 구조체에도 연결할 수 있어요. 위와 마찬가지로 타입을 include하거나 상속하는 타입들에게 상속됩니다.

출처: Crystal 공식 문서

더 알아보기 (Learn more)