Class 클래스
Class 클래스
Ruby에서 클래스는 일급 객체(First-class object)예요. 즉 각 클래스 자체가 Class 클래스의 인스턴스라는 뜻이에요. class Name ... end처럼 새 클래스를 만들면, 내부적으로 Class 타입의 객체가 초기화되어 상수 Name에 담겨요.
출처: Ruby 4.0 API
본문
보통 새 클래스는 다음과 같이 만들어요:
class Name
# some code describing the class behavior
end
새 클래스가 만들어지면 Class 타입의 객체가 초기화되어 전역 상수(이 경우 Name)에 할당돼요.
Name.new로 새 객체를 만들 때는 기본적으로 Class의 new 메서드가 실행돼요. Class에서 new를 오버라이드하면 이 과정을 직접 볼 수 있어요:
class Class
alias old_new new
def new(*args)
print "Creating a new ", self.name, "\n"
old_new(*args)
end
end
class Name
end
n = Name.new
출력:
Creating a new Name
클래스, 모듈, 객체는 서로 밀접하게 얽혀 있어요. 아래 다이어그램에서 세로 화살표는 상속을, 괄호는 메타클래스(metaclass)를 나타내요. 모든 메타클래스는 Class 클래스의 인스턴스예요.
+---------+ +-...
| | |
BasicObject-----|-->(BasicObject)-------|-...
^ | ^ |
| | | |
Object---------|----->(Object)---------|-...
^ | ^ |
| | | |
+-------+ | +--------+ |
| | | | | |
| Module-|---------|--->(Module)-|-...
| ^ | | ^ |
| | | | | |
| Class-|---------|---->(Class)-|-...
| ^ | | ^ |
| +---+ | +----+
| |
obj--->OtherClass---------->(OtherClass)-----------...
Class Methods
new(super_class=Object) → a_class
new(super_class=Object) { |mod| ... } → a_class
주어진 superclass(또는 인자를 안 주면 Object)를 상속받는 익명(이름 없는) 클래스를 새로 만들어요. 클래스 객체를 상수에 할당하면 그 이름이 붙어요.
블록을 주면 블록에 클래스 객체가 전달되고, class_eval처럼 이 클래스의 컨텍스트에서 평가돼요.
fred = Class.new do
def meth1
"hello"
end
def meth2
"bye"
end
end
a = fred.new #=> #<#<Class:0x100381890>:0x100376b98>
a.meth1 #=> "hello"
a.meth2 #=> "bye"
보통 클래스처럼 다루고 싶다면 클래스를 대문자로 시작하는 상수에 할당하면 돼요.
Public Instance Methods
allocate() → obj
class 클래스의 새 객체를 위한 공간만 할당하고, 새 인스턴스의 initialize를 호출하지 않아요. 반환된 객체는 반드시 class의 인스턴스여야 해요.
klass = Class.new do
def initialize(*args)
@initialized = true
end
def initialized?
@initialized || false
end
end
klass.allocate.initialized? #=> false
attached_object → object
수신자가 그 싱글턴 클래스인 객체를 돌려줘요. 클래스가 싱글턴 클래스가 아니면 TypeError가 발생해요.
class Foo; end
Foo.singleton_class.attached_object #=> Foo
Foo.attached_object #=> TypeError: `Foo' is not a singleton class
Foo.new.singleton_class.attached_object #=> #<Foo:0x000000010491a370>
TrueClass.attached_object #=> TypeError: `TrueClass' is not a singleton class
NilClass.attached_object #=> TypeError: `NilClass' is not a singleton class
new(args, ...) → obj
allocate로 class 클래스의 새 객체를 만든 뒤, 그 객체의 initialize 메서드를 args를 넘겨 호출해요. .new로 객체를 만들 때 실제로 호출되는 메서드가 바로 이것이에요.
subclasses → array
수신자가 그 클래스의 직접 superclass인 클래스들의 배열을 돌려줘요. 싱글턴 클래스는 제외하고요. 반환 배열의 순서는 정의되어 있지 않아요.
class A; end
class B < A; end
class C < B; end
class D < A; end
A.subclasses #=> [D, B]
B.subclasses #=> [C]
C.subclasses #=> []
익명 서브클래스(상수와 연결되지 않은)도 반환돼요:
c = Class.new(A)
A.subclasses # => [#<Class:0x00007f003c77bd78>, D, B]
부모는 서브클래스에 대한 참조를 유지하지 않으며, 서브클래스가 가비지 컬렉션되는 것도 막지 않아요. 즉 서브클래스에 대한 모든 참조가 사라지면 사라질 수 있어요:
# drop the reference to subclass, it can be garbage-collected now
c = nil
A.subclasses
# It can be
# => [#<Class:0x00007f003c77bd78>, D, B]
# ...or just
# => [D, B]
# ...depending on whether garbage collector was run
superclass → a_super_class or nil
class의 superclass를 돌려줘요. 없으면 nil이에요.
File.superclass #=> IO
IO.superclass #=> Object
Object.superclass #=> BasicObject
class Foo; end
class Bar < Foo; end
Bar.superclass #=> Foo
주어진 클래스에 부모 클래스가 없으면 nil을 돌려줘요:
BasicObject.superclass #=> nil
inherited(subclass)
현재 클래스의 서브클래스가 만들어질 때마다 호출되는 콜백이에요.
예시:
class Foo
def self.inherited(subclass)
puts "New subclass: #{subclass}"
end
end
class Bar < Foo
end
class Baz < Bar
end
출력:
New subclass: Bar
New subclass: Baz