인스턴스 변수 : self vs @


179

다음은 몇 가지 코드입니다.

class Person
  def initialize(age)
    @age = age
  end

  def age
    @age
  end

  def age_difference_with(other_person)
    (self.age - other_person.age).abs
  end

  protected :age
end

내가 알고 싶은 것은 사용 사이의 차이 @ageself.ageage_difference_with방법.

답변:


260

쓰면 @age인스턴스 변수에 직접 액세스합니다 @age. 쓰기 self.age는 객체에게 메시지를 보내도록 지시하는데 age, 보통 인스턴스 변수를 반환 @age하지만 age주어진 서브 클래스에서 메소드가 구현되는 방식 에 따라 다른 많은 작업을 수행 할 수 있습니다. 예를 들어 MiddleAgedSocialite 클래스를 사용하여 실제보다 나이가 10 세 미만임을 항상보고 할 수 있습니다. 또는 실제로는 PersistentPerson 클래스가 영구 저장소에서 해당 데이터를 느리게 읽고 모든 영구 데이터를 해시로 캐시 할 수 있습니다.


2
한 번 레일에서 책을 읽었 으며이 self와 @의 차이점을 이해하지 못하므로 공용 인터페이스를 사용하여 데이터를 만들려면 항상 set.getter가 아닌 내 메소드에서 self.var_name을 사용해야합니다. getter와 setter에서 정의하는 데 시간을 보냈습니다.
sarunw 2009

1
... 영어로 ... 여러 가지로 무엇을 의미합니까? 나는 마지막 두 가지 예를 얻지 못했습니다.
user2167582

23

차이점은 메소드 사용과 메소드 사용을 분리한다는 것입니다. 속성의 구현이 변경되는 경우 (생년월일을 유지 한 다음 현재 시간과 생년월일의 차이를 기준으로 연령을 계산하는 경우) 분석법에 따른 코드를 변경할 필요가 없습니다. 이 속성을 직접 사용한 경우 코드의 다른 영역으로 변경 내용을 전파해야합니다. 이런 점에서 클래스에서 제공하는 인터페이스를 사용하는 것보다 속성을 직접 사용하는 것이 더 취약합니다.


15
self.age가 인스턴스 변수 또는 인스턴스 메소드를 참조 할 수 있기 때문에?
놀란 에이미

@. @ ... 슬프다.
cyc115

7

Struct.new초기화 프로그램을 생성하는 깔끔한 방법 인 클래스를 상속 할 때 경고하십시오 ( Ruby에서 초기화 프로그램을 생성하는 방법? )

class Node < Struct.new(:value)
    def initialize(value)
        @value = value
    end
    def show()
        p @value
        p self.value # or `p value`
    end
end 

n = Node.new(30)
n.show()

돌아올 것이다

30
nil

그러나 이니셜 라이저를 제거하면

nil
30

클래스 정의

class Node2
    attr_accessor :value
    def initialize(value)
        @value = value
    end
    def show()
        p @value
        p self.value
    end
end

생성자를 제공해야합니다.

n2 = Node2.new(30)
n2.show()

돌아올 것이다

30
30

@Prosseek 예제 덕분에 현재 Ruby on Rails를 배우고 있으며 루비가 불필요하게 복잡하다는 느낌을주는 일종의 동작입니다.
cyc115

3

첫 번째 대답은 전적으로 정확하지만 친숙한 초보자로서 그것이 의미하는 바를 즉시 알지 못했습니다 (메시지를 자신에게 보내는가? 어 ....). 짧은 예가 도움이 될 것이라고 생각합니다.

class CrazyAccessors
  def bar=(val)
    @bar = val - 20 # sets @bar to (input - 20)
  end
  def bar
    @bar
  end

  def baz=(value)
    self.bar = value # goes through `bar=` method, so @bar = (50 - 20)
  end

  def quux=(value)
    @bar = value     # sets @bar directly to 50
  end
end

obj  = CrazyAccessors.new
obj.baz = 50
obj.bar  # => 30
obj.quux = 50
obj.bar  # => 50

8
이 예제는 상황을 더 혼란스럽게 만들었습니다.
Oskar Holmkratz

1
죄송하지만 예제에 대한 설명이 충분하지 않습니다. 나는 당신의 추론을 따를 수 없습니다.
kouty

스몰 토크에서 온 누군가가 "물건이 자신에게 메시지를 보낸다"고 말합니다. 파이썬에서 온 누군가는 객체가 "자체에 메소드를 호출한다"고 말할 것입니다. 혼동하지 마십시오. 그들은 정확히 같은 것입니다. (의미 론적 순수 주의자는 동적 타이핑을 사용하는 언어에 대해서만 동일하고 C ++ 가상 메소드 호출이 메시지를 보내는 것과 정확히 동일하지 않다고 반대 할 수 있습니다. 순수 주의자는 정확하지만 아마도이 질문의 범위를 벗어난 것입니다 / answer.)
GrandOpener

나는 예를 좋아하지만 실제로 무슨 일이 일어나고 있는지에 대한 의견을 더 제공하십시오. 하드없는 설명과 함께 따라하기
CalamityAdam

2

차이가 없습니다. 나는 그것이 단지 보는 다큐멘터리 값에 대해 수행 된 것으로 의심 self.age하고 other_person.age서로 가까이.

나중에 사용하면 실제 getter를 작성할 수 있으며 인스턴스 변수를 반환하는 것보다 복잡한 작업을 수행 할 수 있다고 생각합니다.이 경우 메서드를 변경할 필요가 없습니다.

그러나 객체의 구현이 변경된 경우 다른 메소드를 변경하는 것이 합리적이라고 생각할 가능성은 거의 없습니다.

어쨌든 age속성의 추상화는 여전히 self일반 적으로 age접근자를 호출 했기 때문에 의 명시 적 사용을 설명하지 않습니다 .


당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.