Program Tip

퍼블릭 데이터 멤버 vs 게터, 세터

programtip 2020. 10. 31. 10:03
반응형

퍼블릭 데이터 멤버 vs 게터, 세터


저는 현재 Qt와 C ++에서 일하고 있습니다. 개인 데이터 멤버와 공용 멤버 함수가있는 클래스가 있습니다. 클래스에서 사용할 수있는 데이터 멤버에 대한 공개 getter 및 setter가 있습니다.

이제 내 질문은 우리 클래스에 데이터 멤버에 대한 getter와 setter가 있다면 해당 데이터 멤버를 비공개로 만드는 것이 중요한 이유는 무엇입니까? 나는 기본 클래스에 개인 데이터 멤버를 갖는 것이 논리적으로 들리는 것에 동의합니다. 그러나 그 외에도 개인 멤버를 갖는 것과 그들의 게터와 세터는 저에게 논리적이지 않은 것 같습니다.

아니면 getter와 setter가 전혀 필요하지 않도록 모든 변수를 공용으로 만들 수 있습니까? 그것들을 갖는 것이 좋은 습관입니까? 개인 멤버가 데이터 추상화를 보장한다는 것을 알고 있지만 getter와 setter를 사용하면 실제로 해당 변수에 매우 쉽게 액세스 할 수 있습니다. 이에 관한 모든 조언을 환영합니다.


둘 다 아닙니다. 일을하는 방법이 있어야합니다. 이러한 것 중 하나가 특정 내부 변수와 일치하는 경우 훌륭하지만이를 클래스 사용자에게 전할 수있는 것은 없습니다.

비공개 데이터는 비공개이므로 원할 때마다 구현을 교체 할 수 있습니다 (전체 재 구축을 수행 할 수 있지만 이는 다른 문제입니다). Genie를 병에서 꺼내면 다시 밀어 넣을 수 없습니다.

편집 : 다른 답변에 대한 의견에 따라.

여기서 내 요점은 당신이 잘못된 질문을하고 있다는 것입니다. getter / setter를 사용하거나 공용 구성원을 갖는 것과 관련된 모범 사례는 없습니다. 특정 개체에 가장 적합한 것은 무엇이며 특정 실제 사물 (또는 게임의 경우 가상 사물)을 모델링하는 방법 만 있습니다.

개인적으로 게터 / 세터는 두 가지 악 중에서 더 적습니다. 일단 getter / setter를 만들기 시작하면 사람들은 어떤 데이터가 표시되어야하고 어떤 데이터가 표시되지 않아야하는지에 대한 비판적인 시각으로 객체 디자인을 중단하기 때문입니다. 공개 회원의 경우 모든 것을 공개하려는 경향이 있기 때문에 더욱 악화됩니다.

대신, 그 객체가하는 일과 그 객체가되는 것이 무엇을 의미하는지 조사하십시오. 그런 다음 해당 객체에 자연스러운 인터페이스를 제공하는 메서드를 만듭니다. 자연스러운 인터페이스는 getter와 setter를 사용하여 내부 속성을 노출하는 것을 포함합니다. 그러나 중요한 부분은 미리 생각하고 디자인 정당한 이유로 게터 / 세터를 만들었다는 것입니다.


아니요, 원격으로도 같은 것이 아닙니다.

클래스 인터페이스에 대한 다양한 접근 방식으로 달성 할 수있는 보호 / 구현 은닉 수준에는 여러 가지가 있습니다.


1. 공개 데이터 멤버 :

  • 데이터 멤버에 대한 읽기 및 쓰기 (const가 아닌 경우) 액세스를 모두 제공합니다.
  • 데이터 객체가 물리적으로 존재하고 물리적으로이 클래스의 멤버라는 사실을 노출합니다 (해당 데이터 멤버에 대한 멤버 포인터 유형의 포인터를 만들 수 있음).
  • 데이터 멤버에 대한 lvalue 액세스를 제공합니다 (멤버에 대한 일반 포인터를 만들 수 있음).


2. 데이터에 대한 참조를 반환하는 메서드 (개인 데이터 멤버 일 수 있음) :

  • 데이터에 대한 읽기 및 쓰기 (const가 아닌 경우) 액세스를 모두 제공합니다.
  • 데이터 객체가 물리적으로 존재하지만 물리적으로이 클래스의 멤버 라는 사실을 노출하지 않습니다 (데이터에 대한 멤버 포인터 유형의 포인터를 생성 할 수 없음).
  • 데이터에 대한 lvalue 액세스를 제공합니다 (일반 포인터를 만들 수 있음).


3. Getter 및 / 또는 setter 메서드 (개인 데이터 멤버에 액세스 할 수 있음) :

  • 속성에 대한 읽기 및 / 또는 쓰기 액세스를 모두 제공합니다.
  • 이 클래스에 물리적으로 존재하는 것은 말할 것도없고 데이터 객체가 물리적으로 존재한다는 사실을 노출하지 않습니다 ( 해당 데이터에 대한 멤버 포인터 유형의 포인터 또는 해당 문제에 대한 모든 종류의 포인터를 생성 할 수 없음).
  • 데이터에 대한 lvalue 액세스를 제공하지 않습니다 (일반 포인터를 만들 수 없음).

getter / setter 접근 방식은 속성이 물리적 객체에 의해 구현된다는 사실조차 드러내지 않습니다. 즉, getter / setter 쌍 뒤에 물리적 데이터 멤버가 없을 수 있습니다.

위의 내용을 살펴보면 누군가 getter와 setter 쌍이 공개 데이터 멤버와 동일하다고 주장하는 것을 보는 것은 이상합니다. 사실, 그들은 공통점이 없습니다.

물론 각 접근 방식에는 변형이 있습니다. 예를 들어, getter 메서드는 데이터에 대한 const 참조를 반환하여 (2)와 (3) 사이에 배치 할 수 있습니다.


각 데이터 항목에 대한 getter 및 setter가있는 경우 데이터를 비공개로 설정할 필요가 없습니다. 그렇기 때문에 각 데이터 항목에 대해 getter 및 setter를 사용하는 것은 나쁜 생각입니다. std :: string 클래스를 고려하십시오. (아마도) 하나의 getter, size () 함수가 있고 setter가 전혀 없습니다.

또는 BankAccount객체를 고려하십시오 - SetBalance()현재 잔액을 변경하려면 setter 가 있어야 합니까? 아니요, 대부분의 은행은 그러한 구현에 대해 감사하지 않습니다. 대신 우리는 ApplyTransaction( Transaction & tx ).


Getter 및 Setter를 사용하면 개인 구성원의 입력 / 출력에 논리를 적용하여 데이터에 대한 액세스를 제어 할 수 있습니다 (OO 용어를 알고있는 사용자에 대한 캡슐화).

공개 변수는 거의 항상 바람직하지 않은 제어되지 않고 검증되지 않은 조작을 위해 클래스의 데이터를 공개적으로 공개합니다.

이런 것들에 대해서도 장기적으로 생각해야합니다. 지금은 유효성 검사가 없을 수도 있지만 (이것이 공개 변수가 좋은 생각 인 것처럼 보임) 길을 따라 추가 될 가능성이 있습니다. 미리 추가하면 프레임 워크가 떠나므로 유효성 검사가 이런 방식으로 종속 코드를 손상시키지 않을 것임을 언급 할뿐만 아니라 raod를 리팩토링하지 않아도됩니다.)

그렇다고 각 개인 변수에 자체 getter / setter가 필요하다는 의미는 아닙니다. Neil은 때때로 Getters / Setters가 이해가되지 않는 은행 업무 사례에서 좋은 지적을했습니다.


데이터를 공개합니다. 언젠가 "getter"또는 "setter"에 로직이 필요한 경우 (아주 드물게) 데이터 유형을 오버로드 operator=및 / 또는 operator T(T = 지금 사용중인 유형에 관계없이) 프록시 클래스로 변경할 수 있습니다. 필요한 논리를 구현합니다.

편집 : 데이터에 대한 액세스 제어가 캡슐화를 구성한다는 생각은 기본적으로 거짓입니다. 캡슐화는 데이터에 대한 액세스를 제어 하지 않고 구현 (일반적으로!)의 세부 사항을 숨기는 것 입니다.

캡슐화는 추상화를 보완합니다. 추상화는 개체의 외부에서 볼 수있는 동작을 처리하는 반면 캡슐화는 해당 동작이 구현되는 방법에 대한 세부 정보를 숨기는 것을 처리합니다.

getter 또는 setter를 사용하면 실제로 추상화 수준이 감소 하고 구현이 노출됩니다.이 특정 클래스가 함수 쌍 (getter 및 setter)으로 논리적으로 "데이터"인 것을 구현한다는 것을 클라이언트 코드에서 인식해야합니다. 위에서 제안한대로 프록시를 사용하면 실제 캡슐화가 제공 됩니다. 하나의 모호한 코너 케이스를 제외하고 는 논리적으로 데이터 조각이 실제로 한 쌍의 함수를 통해 구현된다는 사실을 완전히 숨 깁니다 .

물론, 이것은 맥락에서 유지되어야합니다. 일부 클래스의 경우 "데이터"는 전혀 좋은 추상화가 아닙니다. 일반적으로 말하면 데이터 대신 더 높은 수준의 작업을 제공 할 수 있다면 더 좋습니다. 그럼에도 불구하고 가장 유용한 추상화가 데이터를 읽고 쓰는 클래스가 있습니다.이 경우 (추상 된) 데이터는 다른 데이터와 마찬가지로 표시되어야합니다. 값을 가져 오거나 설정하는 데는 단순한 비트 복사 이상의 작업이 포함될 수 있다는 사실은 사용자에게 숨겨야하는 구현 세부 사항입니다.


If you are quite sure your logic is simple, and you never need to do something else when reading/writing a variable, it's better to keep the data public. In C++ case, I prefer to use struct instead of class to emphasize the fact that the data is public.

However, quite often you need to do some other things when accessing data members, or you want to give yourself freedom to add this logic later. In this case, getters and setters are good idea. Your change will be transparent to the clients of your code.

A simple example of additional functionality - you may want log a debug string every time you access a variable.


Aside from the encapsulation concerns (which are reason enough), it is very easy to set a breakpoint whenever the variable is set/accessed when you have getters/setters.


Reasons to use public fields rather than getters and setters include:

  1. There are no illegal values.
  2. The client is expected to edit it.
  3. To be able to write things such as object.X.Y = Z.
  4. To making a strong promise that the value is just a value and there are no side-effects associated with it (and won't be in the future either).

Depending on what sort of software you work on, these might all be really exceptional cases (and if you think you've come across one you're probably wrong) or they might occur all the time. It really depends.

(From Ten Questions on Value-Based Programming.)


On a strictly practical basis, I'd suggest you start by making all of your data members private, AND make their getters and setters private. As you find out what the rest of the world (i.e., your "(l)user community") actually needs, you can expose the appropriate getters and/or setters, or write appropriately-controlled public accessors.

Also (for Neil's benefit), during debugging time, it is sometimes useful to have a convenient place to hang debug prints, and other actions, when a particular data member is read or written. With getters and setters, this is easy. With public data members, it is a huge pain in the posterior.


I've always thought that getters and setters are deliberately verbose in most programming languages specifically to make you think twice about using them - why does your caller need to know about the inner workings of your class should be the question at the front of your mind.


I believe that using getters and setters simply for getting and setting the value is useless. There is no difference between a public member and private one with such methods. Use getters and setters only when you need to control the values somehow or when you think that it might be useful in the future (adding some logic won't make you edit the rest of the code).

As a reference, read C++ guidelines (C.131)


I suggest that you don't have public data members (except for POD structs). I also don't recommend that you have getters and setters for all of your data members. Rather, define a clean public interface for your class. This may include methods that get and/or set property values, and those properties may be implemented as member variables. But don't make getters and setters for all of your members.

The idea is that you separate your interface from your implementation, allowing you to modify the implementation without the users of the class having to change their code. If you expose everything through getters and setters, you've not improved anything over using public data.


Using getters and setters will allow you to modify the way that you give the values to the user.

Consider the following:

double premium;
double tax;

You then write code all over the place using this premium value to get the premium:

double myPremium = class.premium;

Your specs just changed and premium from the user's standpoint needs to be premium + tax

You will have to modify everywhere that that premium value is being used in your code, and add tax to it.

If instead you implemented it as such:

double premium;
double tax;

double GetPremium(){return premium;};

All of your code would be using GetPremium() and your tax change would be one line:

double premium;
double tax;

double GetPremium(){return premium + tax;};

The return value also effects the use of getters and setters. It's a difference to get the value of a variable or to get access to private data member variable. By-value keeps integrity, by-reference or by-pointer not so much.


Getters and Setters exist primarily so that we can control how members are fetched, and how they are set. Getters and setters dont exist only as a way to access a specific member, but to ensure that before we try and set a member, that it perhaps meets certain conditions, or if we fetch it, we could control that we return a copy of that member in the case of a non-primitive type. Overall, you should try and use g/s'ers when you want to pipeline how a data member is to be interacted with, without them would cause the member is be used in an adhoc fashion.

참고URL : https://stackoverflow.com/questions/2977007/public-data-members-vs-getters-setters

반응형