new, initialize, allocate

new, initialize, allocate

클래스에서 new를 호출하면 그 클래스의 인스턴스를 만들 수 있어요:

person = Person.new

여기서 personPerson의 인스턴스입니다.

person으로는 할 수 있는 게 별로 없으니, 여기에 몇 가지 개념을 더해 봅시다. Person은 이름(name)과 나이(age)를 가져요. "Everything is an object" 절에서 객체는 타입이 있고 몇몇 메서드에 응답하며, 그게 객체와 상호작용하는 유일한 방법이라고 했죠. 그래서 nameage 메서드가 둘 다 필요합니다. 이 정보는 항상 at(@) 문자로 시작하는 인스턴스 변수에 저장할 거예요. 우리가 원하는 Person은 원하는 이름과 나이 0으로 시작하길 바랍니다. "존재하게 되는" 부분은 보통 생성자 라고 부르는 특별한 initialize 메서드로 구현해요:

class Person
  def initialize(name : String)
    @name = name
    @age = 0
  end

  def name
    @name
  end

  def age
    @age
  end
end

이제 이렇게 사람을 만들 수 있습니다:

john = Person.new "John"
peter = Person.new "Peter"

john.name # => "John"
john.age  # => 0

peter.name # => "Peter"

(nameString임을 지정해야 했는데 age는 왜 그럴 필요가 없었을까 궁금하다면, 전역 타입 추론 알고리즘을 확인해 보세요.)

참고로 Personnew로 만들지만, 초기화는 new 메서드가 아니라 initialize 메서드에 정의했어요. 왜 그럴까요?

답은, initialize 메서드를 정의하면 Crystal이 new 메서드를 우리를 대신해 이렇게 만들어 주기 때문입니다:

class Person
  def self.new(name : String)
    instance = Person.allocate
    instance.initialize(name)
    instance
  end
end

먼저 self.new 표기를 눈여겨보세요. 이건 Person이라는 클래스에 속하는 클래스 메서드이지, 그 클래스의 특정 인스턴스에 속하는 게 아닙니다. 그래서 Person.new라고 할 수 있는 거죠.

두 번째로, allocate는 주어진 타입의 초기화되지 않은 객체를 만드는 저수준 클래스 메서드입니다. 기본적으로 객체에 필요한 메모리를 할당하고, 그다음 그 객체에 initialize를 호출하며, 마지막으로 인스턴스를 반환해요. 일반적으로 allocateunsafe하기 때문에 직접 호출하지 않지만, newinitialize가 이렇게 연결되어 있다는 기억해 둘 점이죠.

출처: Crystal 공식 문서

더 알아보기 (Learn more)