개체 메서드 내에서 개체 속성에 어떻게 액세스합니까? [닫은]


96

getter / setter 메서드가 아닌 객체 메서드 내에서 객체 속성에 액세스하는 "순수 적"또는 "올바른"방법은 무엇입니까?

객체 외부에서 getter / setter를 사용해야한다는 것을 알고 있지만 내부에서는 다음과 같이하면됩니다.

자바:

String property = this.property;

PHP :

$property = $this->property;

또는 당신은 할 것 :

자바:

String property = this.getProperty();

PHP :

$property = $this->getProperty();

제 Java가 약간 벗어난 경우 용서하십시오. Java로 프로그래밍 한 지 1 년이 지났습니다.

편집하다:

사람들은 내가 개인 또는 보호 변수 / 속성에 대해서만 이야기하고 있다고 가정하고있는 것 같습니다. 내가 OO를 배웠을 때 나는 그것이 공개 된 경우에도 모든 단일 속성에 대해 getter / setters를 사용하도록 배웠습니다 (실제로 나는 어떤 변수 / 속성도 공개하지 말라고 들었습니다). 그래서 나는 처음부터 잘못된 가정에서 출발 할 수 있습니다. 이 질문에 대답하는 사람들은 아마도 당신이 공공 자산을 가져야한다고 말하는 것 같습니다. 그리고 그것들은 내가 배운 것과 내가 말한 것과 반대되는 게터와 세터가 필요하지 않다고 말하는 것 같습니다. 잘. 그것은 아마도 다른 질문에 대한 좋은 주제 일 것입니다 ...

답변:


62

이것은 종교적 전쟁 가능성이 있지만 getter / setter를 사용하는 경우 내부적으로도 사용해야하는 것 같습니다. 둘 다 사용하면 향후 유지 관리 문제가 발생할 수 있습니다 (예 : 누군가 필요한 setter에 코드를 추가 합니다). 해당 속성이 설정 될 때마다 실행되고 속성은 해당 setter가 호출되지 않고 내부적으로 설정됩니다.


속성 값을 Java에서 잘못된 사용의 예로 설정하는 것 외에는 setter에서 다른 작업을 수행하지 않습니다.
euphoria83

1
@ euphoria83 아마도 그렇다고해서 그것이 일어나는 것을 배제하지는 않습니다.
Greg Hurlman 2010 년

원래 답변에 동의합니다. 그러나 클래스 또는 객체 내에서 개인 정보를 설정하거나 가져 오는 경우 getter / setter가 어떤 식 으로든 순환 적이거나 중복되어 코드가 실패하지 않는지 확인해야합니다. getter / setter를 사용할 수없는 경우 직접 액세스하십시오. (예 : getter / setter가 데이터를 조작하기 위해 보조 (개인 / 보호) 방법에 액세스합니다.)
Rick Mac Gillis

43

개인적으로 일관성을 유지하는 것이 중요하다고 생각합니다. 게터와 세터가 있으면 사용하십시오. 내가 필드에 직접 액세스하는 유일한 시간은 접근자가 많은 오버 헤드를 가질 때입니다. 불필요하게 코드가 부풀어 오르는 것처럼 느껴질 수 있지만 앞으로는 많은 두통을 확실히 줄일 수 있습니다. 고전적인 예 :

나중에 필드가 작동하는 방식을 바꾸고 싶을 수 있습니다. 즉석에서 계산해야하거나 백업 저장소에 다른 유형을 사용하고 싶을 수도 있습니다. 속성에 직접 액세스하는 경우 이와 같은 변경은 한 번에 엄청난 양의 코드를 깨뜨릴 수 있습니다.


26

그 정서가 만장일치로 놀랍습니다. getters 이고 세터가 훌륭하고 훌륭 . 나는 Allen Holub의 " Getters And Setters Are Evil " 의 방화 기사를 제안합니다 . 물론 제목은 충격적인 가치를위한 것이지만 저자는 타당한 지적을합니다.

기본적으로, 당신이있는 경우 getterssetters 각각의 모든 개인 필드, 공용 좋은으로 해당 필드를 만들고있다. 당신은 그것을 호출하는 모든 클래스에 파급 효과없이 private 필드의 유형을 변경하기가 매우 어려울 것입니다 getter.

더욱이, 엄격하게 OO 관점에서 객체는 (희망적으로) 단일 책임에 해당하는 메시지 (메소드)에 응답해야합니다. 대부분의 getterssetters구성 개체에 대해 의미가 없습니다.Pen.dispenseInkOnto(Surface)나보다 더 의미가 Pen.getColor()있습니다.

게터와 세터는 또한 클래스 사용자가 개체에 데이터를 요청하고 계산을 수행 한 다음 절차 적 프로그래밍으로 더 잘 알려진 개체에 다른 값을 설정하도록 권장합니다. 처음에하려고했던 것을 단순히 대상에게 지시하는 것이 더 낫습니다. 정보 전문가 라고도 함 관용구 .

그러나 게터와 세터는 UI, 지속성 등 레이어 경계에서 필요한 악입니다. C ++의 friend 키워드, Java의 패키지 보호 액세스, .NET의 내부 액세스 및 Friend Class Pattern 과 같은 클래스의 내부에 대한 제한된 액세스 는 getters이를 필요로하는 사람들에게만 가시성 과 setter를 줄이는 데 도움이 될 수 있습니다.


19

속성이 어떻게 사용되는지에 따라 다릅니다. 예를 들어 이름 속성이있는 학생 개체가 있다고 가정합니다. 아직 검색되지 않은 경우 Get 메서드를 사용하여 데이터베이스에서 이름을 가져올 수 있습니다. 이렇게하면 데이터베이스에 대한 불필요한 호출을 줄일 수 있습니다.

이제 개체에 이름이 호출 된 횟수를 계산하는 개인 정수 카운터가 있다고 가정 해 보겠습니다. 개체 내부에서 Get 메서드를 사용하면 잘못된 개수가 생성되므로 사용하지 않는 것이 좋습니다.


Student 개체가 비즈니스 / 도메인 개체 인 경우 이제 인프라 세부 정보를 혼합하고 있습니다. 이상적으로는 비즈니스 / 도메인 개체는 비즈니스 / 도메인 논리에만 관련되어야합니다.
moffdub

다음과 같이 getter에 일종의 부울을 추가하면 어떻게됩니까? PHP : public function getName ($ outsideCall = true) {if ($ outsideCall) {$ this-> incrementNameCalled (); } return $ this-> name; } 그런 다음 Object 자체 내에서 get name을 호출하면 다음과 같이 증가하지 않도록 할 수 있습니다. PHP : $ name = $ this-> getName (false); 여기서 배 밖으로 나가는 건가요?
cmcculloh 2010-01-23

14

PHP는 마법 방법을 포함하여이 처리 할 수있는 방법의 무수 제공 __get등을 __set,하지만 난 명시 적 getter 및 setter를 선호합니다. 그 이유는 다음과 같습니다.

  1. 유효성 검사는 setter (및 해당 문제에 대한 getter)에 배치 할 수 있습니다.
  2. Intellisense는 명시 적 방법으로 작동합니다.
  3. 속성이 읽기 전용인지, 쓰기 전용인지 또는 읽기-쓰기인지에 대한 질문 없음
  4. 가상 속성 (즉, 계산 된 값)을 검색하는 것은 일반 속성과 동일하게 보입니다.
  5. 실제로 어디에도 정의되지 않은 객체 속성을 쉽게 설정할 수 있으며 문서화되지 않습니다.

13

여기서 배 밖으로 나가는 건가요?

혹시 ;)

또 다른 접근 방식은 개인 / 보호 방법을 사용하여 실제로 가져 오기 (캐싱 / db / etc)를 수행하고 개수를 증가시키는 공용 래퍼를 사용하는 것입니다.

PHP :

public function getName() {
    $this->incrementNameCalled();
    return $this->_getName();
}

protected function _getName() {
    return $this->name;
}

그런 다음 객체 자체 내에서 :

PHP :

$name = $this->_getName();

이 방법을 사용하면 여전히 첫 번째 인수를 다른 항목에 사용할 수 있습니다 (예 : 여기에서 캐시 된 데이터를 사용할지 여부에 대한 플래그를 보내는 것과 같은).


12

여기서 요점을 놓치고 있어야합니다. 객체 내부에서 getter를 사용하여 해당 객체의 속성에 액세스하는 이유는 무엇입니까?

결론에 도달하면 getter는 getter를 호출해야하며 getter를 호출해야합니다.

따라서 객체 메서드 내부에서 속성에 직접 액세스한다고 말하고 싶습니다. 특히 해당 객체에서 다른 메서드를 호출하는 것으로 보는 것 (어쨌든 속성에 직접 액세스 한 다음 반환)은 무의미하고 낭비적인 연습 일뿐입니다 (또는 질문을 오해 했습니까? ).


나는 당신이 코멘트에 있던 같은 필요에 의해 주도되었다 ... 게다가 그것은 폐쇄하지 대답했다)
알 반스

8

순수주의 OO 방식은 Tell Do n't Ask 접근 방식 을 사용하여 둘 다 피하고 데메테르법칙을 따르는 것 입니다.

두 클래스 를 밀접하게 연결 하는 객체의 속성 값을 가져 오는 대신 객체를 매개 변수로 사용합니다.

  doSomethingWithProperty() {
     doSomethingWith( this.property ) ;
  }

속성이 네이티브 유형 (예 : int) 인 경우 액세스 방법을 사용하고 프로그래밍 도메인이 아닌 문제 도메인에 대해 이름을 지정합니다.

  doSomethingWithProperty( this.daysPerWeek() ) ;

이를 통해 캡슐화 및 사후 조건 또는 종속 불변을 유지할 수 있습니다. 또한 setter 메서드를 사용하여 사전 조건이나 종속 불변을 유지할 수 있지만 setter 이름을 지정하는 함정에 빠지지 말고 관용구를 사용할 때 이름 지정에 대한 Hollywood Principle로 돌아가십시오.


8

객체 내에서도 접근 자 메서드를 사용하는 것이 좋습니다. 내 마음에 즉시 떠오르는 요점은 다음과 같습니다.

  1. 객체 외부에서 이루어진 액세스와 일관성을 유지하기 위해 수행해야합니다.

  2. 경우에 따라 이러한 접근 자 메서드는 필드에 액세스하는 것 이상을 수행 할 수 있습니다. 추가 처리를 수행 할 수 있습니다 (하지만 드물지만). 이 경우 필드에 직접 액세스하면 해당 추가 처리를 놓치고 있음을 의미하며 이러한 처리가 이러한 액세스 중에 항상 수행되어야하는 경우 프로그램이 잘못 될 수 있습니다.


8

"순수한"으로 "대부분의 캡슐화"를 의미하는 경우 일반적으로 모든 필드를 비공개로 선언 한 다음 클래스 자체에서 "this.field"를 사용합니다. 하위 클래스를 포함한 다른 클래스의 경우 getter를 사용하여 인스턴스 상태에 액세스합니다.


7

setter / getter를 사용하면 코드를 더 쉽게 읽을 수 있습니다. 나는 또한 다른 클래스가 메서드를 사용할 때 제공하는 컨트롤을 좋아하고 데이터를 변경하면 속성이 저장할 것입니다.


7

공용 또는 보호 된 속성이있는 개인 필드. 값에 대한 액세스는 속성을 거쳐야하며 메서드에서 두 번 이상 사용되는 경우 로컬 변수에 복사해야합니다. 응용 프로그램의 나머지 부분이 완전히 조정되고, 흔들리고, 그렇지 않으면 관련 속성을 통해 값에 액세스하는 것이 병목이 된 부분에 최적화 된 경우에만 시작해야합니다. 속성 이외의 다른 항목이 백업 변수에 직접 닿도록하는 것을 고려합니다.

.NET 개발자는 디자인 타임에 지원 변수를 볼 수도 없기 때문에 자동 속성을 사용하여이를 적용 할 수 있습니다.


7

때에 따라 다르지. 다른 무엇보다 스타일 문제이며 엄격한 규칙이 없습니다.


7

내가 자립하기 때문에 틀릴 수 있지만 Java 클래스에서 공용 속성을 사용하지 않으며 항상 비공개이거나 보호되므로 외부 코드가 getter / setter에 액세스해야합니다. 유지 보수 / 수정 목적으로 더 좋습니다. 그리고 내부 클래스 코드의 경우 ... getter 메서드가 사소한 경우 속성을 직접 사용하지만 원하는 경우 이벤트를 실행하는 코드를 쉽게 추가 할 수 있기 때문에 항상 setter 메서드를 사용합니다.


7

속성을 편집하지 않으면 get_property()다른 개체 내부의 MySQLi 개체와 같은 특별한 경우가 아니라면 public 메서드를 사용 합니다.이 경우 속성을 public으로 만들고이를 $obj->object_property.

객체 내부에는 항상 $ this-> property입니다.


5

음, C # 3.0 속성의 기본 구현을 사용하면 결정이 내려집니다. (개인적인) 속성 설정기를 사용하여 속성을 설정해야합니다.

개인적으로 private member-behind를 사용하지 않으면 초기화 할 때나 캐싱 / 지연 로딩이 관련 될 때와 같이 개체가 바람직하지 않은 상태로 떨어질 때만 사용합니다.


5

cmcculloh 의 대답이 마음들지만 가장 정확한 대답은 Greg Hurlman 의 대답 인 것 같습니다 . 처음부터 사용하기 시작했거나 사용하는 데 익숙한 경우 항상 getter / setter를 사용하십시오.

제쳐두고 개인적으로 getter / setter를 사용하면 코드를 더 쉽게 읽고 나중에 디버깅 할 수 있다는 것을 알게되었습니다.


4

댓글 중 일부에서 언급했듯이 : 때로는해야 할 때도 있고, 안되는 경우도 있습니다. private 변수의 가장 큰 부분은 무언가를 변경할 때 사용되는 모든 위치를 볼 수 있다는 것입니다. getter / setter가 필요한 작업을 수행하는 경우 사용하십시오. 중요하지 않다면 결정하십시오.

반대로 getter / setter를 사용하고 누군가가 getter / setter를 변경하는 경우 모든 위치를 분석해야하는 경우 getter 및 setter가 내부적으로 사용되어 무언가를 엉망으로 만드는지 확인해야합니다.

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