TIL/BOOK: Programming Ruby

24.1 객체와 클래스

parksisi 2020. 12. 13. 21:52

어째서 첫글이 24.1 부터냐고? 책이 너무 두꺼워서이다. 두꺼운 책은 첫 장 펼치기가 너무 부담스럽다. 그래서 궁금한 게 생길때만 찾아보는, 게릴라 전략을 택했다. 양심은 있어서 블로그 글로 정리하기로 했다. 그러니 내 44,000원아 너무 서운해 하지마..

 

객체와 클래스는 항상 헷갈린다. 알것같다 싶으면 내가 몰랐던 개념이 툭 튀어나오고, 알고 쓴다 생각하다가도 알고보면 전혀 모르고 있었고. 그래서 책을 뒤적거려봤다. 

 

 

self와 메서드 호출

루비에는 현재 객체라는 개념이 있다. 현재 객체는 self를 통해 참조할 수 있다. 이 self는 루비에서 두 가지 중요한 역할을 하는데, 아래와 같다.

1. 인스턴스 변수에 접근하고자 시도하면 루비는 self를 통해 인스턴스 변수를 찾는다.

2. 메서드를 호출할 때 핵심적인 역할을 한다. 아래에 부연 설명

 

메서드 호출은 수신자가 있는 호출과 없는 호출로 나뉜다. 여기서 수신자란 객체를 말한다.

items.size 와 같이 메서드를 호출한다면, items가 참조하는 객체가 수신자이다.

puts "hi" 의 예처럼 명시적인 수신자가 없는 경우는 현재 객체를 수신자로 삼는다. 이를 통해 self의 클래스에서 호출된 메서드를 검색한다. 만약 못찾는다면 그 상위의 클래스를 살펴보고 없다면 또 그 위의 클래스를 살펴보는 식으로 검색한다. 

items.size와 같이 명시적인 수신자가 있는 경우에도 메서드가 호출되는 과정은 비슷하다. 한가지 차이점은 self가 달라진다는 점이다. 수신자가 있는 경우 메서드 검색 과정 전에 루비는 self를 수신자로 설정한다. 그리고 메서드 호출이 끝나고 나면 self를 메서드 호출 전의 값으로 되돌려 놓는다 

 

코드를 통해 다시 한 번 살펴보자.

 

class Test
    def one
    	@var = 90
    	two
    end
    
    def two
    	puts @var
    end
end

t = Test.new
t.one   #result -> 90

 

t.one을 통해 메서드를 호출하면, 루비는 self를 t로 바꾸고 t의 클래스에서 메서드를 검색한다. 

Test 클래스 안에서 one을 찾았다. one이라는 메서드 안에서 @var에 90을 대입한다. 현재 객체는 t이므로 이 인스턴스 변수는 현재 객체에 결합되어 있다. 

다음 행에서 one은 two를 호출한다. 이때 two는 명시적인 수신자가 없기 때문에 self는 변하지 않는다. 따라서 루비는 t의 클래스 Test에서 two를 찾는다. 

two메서드는 인스턴스 변수 @var를 참조하고 있다. 루비는 현재 객체 안에서 이 변수를 탐색하고, 메서드 one에 의해 설정된 같은 변수를 찾는다. 

마지막 puts메서드 역시 같은 원리로 실행된다. 이번에도 수신자가 없기 때문에 self는 변하지 않는다. 물론 puts는 현재 개체의 클래스, 즉 Test엔 없으니 상위 클래스로 올라가며 탐색한다. 

메서드 호출이 끝나면 self를 원래 값으로 재설정한다. 

 

self와 클래스 정의

앞서 말했듯이 self는 수신자가 명시적으로 주어지면 변한다. 또한 클래스 정의에 의해서도 self는 달라질 수 있다. 아래 코드를 보자.

 

class Test
    puts "self = #{self}"
    puts "Class of self = #{self.class}"
end

실행결과: 

self = Test
Class of self = Class

클래스 정의에 의해 self는 정의되고 있는 클래스(Test)의 클래스 객체로 설정되었다.

참고로 이러한 이유로 클래스 정의에서 설정된 인스턴수 변수는 클래스 메서드에서 사용할 수 있다.