같은 클래스에있는 다른 개체의 개인 필드에 액세스


91
class Person 
{
   private BankAccount account;

   Person(BankAccount account)
   {
      this.account = account;
   }

   public Person someMethod(Person person)
   {
     //Why accessing private field is possible?

     BankAccount a = person.account;
   }
}

디자인은 잊어주세요. 나는 OOP가 개인 객체가 클래스에 개인임을 지정한다는 것을 알고 있습니다. 내 질문은 왜 개인 필드가 개체 수준 액세스가 아닌 클래스 수준 액세스를 갖도록 OOP가 설계 되었습니까?


5
OP는 "someMethod"에 전달 된 "Person"개체를 별도의 개체로 간주하므로 메서드는 "Person"클래스 내에 있더라도 개인 멤버에 대한 액세스 권한이 없어야합니다.
Inisheer

1
일부 언어는이를 수행하지 않습니다 (예 : Newspeak). 이유에 대해 좋은 대답을 얻지 못할 것입니다. 지정된 상황에서 거꾸로 작동하는 답변을 얻을 수 있습니다.
톰 Hawtin의 - tackline

someMethod유효하지 않습니다. 아무것도 반환하지 않습니다. 이어야합니다 void.
Nicolas Barbulesco 2013-08-21

1
그렇지 않다면 복사 생성자와 할당 연산자 imo를 작성하는 것이 매우 어려울 것입니다.
로지나

답변:


68

나는 또한 대답이 조금 궁금합니다.

내가 찾은 가장 만족스러운 답변은 여기 다른 게시물의 Artemix에서 가져온 것입니다 (AClass의 이름을 Person 클래스로 변경하고 있습니다). 왜 객체 수준 대신 클래스 수준 액세스 수정자가 있습니까?

private 한정자는 캡슐화 원칙을 적용합니다.

아이디어는 Person 구현이 시간이 지남에 따라 변경 될 수 있기 때문에 '외부 세계'가 Person 내부 프로세스를 변경해서는 안된다는 것입니다 (그리고 구현의 차이를 수정하기 위해 전체 외부 세계를 변경해야합니다-거의 불가능합니다).

Person의 인스턴스가 다른 Person 인스턴스의 내부에 액세스 할 때 두 인스턴스 모두 항상 Person의 구현 세부 정보를 알고 있는지 확인할 수 있습니다. 내부 프로세스의 로직이 변경되면 Person의 코드를 변경하기 만하면됩니다.

편집 : Artemix의 답변에 투표 하십시오 . 복사하여 붙여 넣는 중입니다.


4
이것이 아마도 이유 일 것입니다. 그러나 이것은 나쁜 생각 입니다. 이것은 나쁜 습관을 조장합니다. Person클래스에서의 필드에 액세스하는 개발자 Person는 전체 클래스의 구현을 알 필요가 없습니다. 접근자가 수행하는 작업을 몰라도 접근자를 사용하는 것이 좋습니다.
Nicolas Barbulesco 2013-08-21

16
@NicolasBarbulesco 대답에 주어진 이유는 건전하다고 생각합니다. 예를 들어 equals(Object)Java 클래스에서 메소드 를 구현하여 Person객체가 Person. 두 인스턴스가 동일한 지 외부 세계에서 확인하도록 할 수 있지만 공용 접근 자 메서드를 사용하여 외부 세계에 대한 동등성을 확인하는 데 필요한 클래스의 모든 개인 필드를 노출하지 않을 수 있습니다. private필드에 대한 클래스 수준 액세스 권한이 있으면 이러한 공용 메서드를 구현할 필요없이 이러한 메서드를 구현할 수 있습니다.
Malte Skoruppa 2015

1
@MalteSkoruppa-이것은 좋은 예입니다 (메소드 구현 equals).
Nicolas Barbulesco 2015

@MalteSkoruppa-그러나 메서드 구현은 equals개인 접근 자를 호출하여 수행 할 수 있습니다.
Nicolas Barbulesco 2015

@NicolasBarbulesco 물론 그렇습니다.하지만 요점은 개인 접근자를 사용하든 메서드를 구현하기 위해 개인 필드에 직접 액세스하든 private클래스 수준 액세스 권한을 부여해야한다는 것입니다. 나는 접근자를 사용하는 것이 일반적으로 좋은 습관이라는 데 동의하지만,이 경우에는 대부분 컨텍스트와 개인적인 스타일의 문제입니다. 모두 조슈아 블로흐 있습니다 효과적인 자바 에서 (항목 8) 및 탈 코헨 이 박사 돕 스는 기사를 구현하는 방법을 논의 할 때 직접 코드 목록에서 개인 필드에 액세스 equals.
Malte Skoruppa 2015

17

Java 언어 사양, 섹션 6.6.1을 참조하십시오 . 접근성 결정

그것은 말한다

그렇지 않고 멤버 또는 생성자가 선언 된 경우 멤버 또는 생성자의 선언 private을 포함하는 최상위 클래스 (§7.6)의 본문 내에서 발생하는 경우에만 액세스가 허용됩니다.

자세한 내용은 위의 링크를 클릭하십시오. 그래서 대답은 다음과 같습니다. James Gosling과 다른 Java 작성자가 그렇게하기로 결정했기 때문입니다.


16

좋은 질문. 객체 수준 액세스 수정자는 캡슐화 원칙을 더욱 강화할 것으로 보입니다.

그러나 실제로는 그 반대입니다. 예를 들어 보겠습니다. 해당 개체의 전용 멤버에 액세스 할 수없는 경우 생성자에서 개체를 전체 복사하려고한다고 가정합니다. 그런 다음 가능한 유일한 방법은 모든 개인 구성원에 공용 접근자를 추가하는 것입니다. 이것은 당신의 개체를 만들 것 알몸 시스템의 모든 다른 부분.

따라서 캡슐화는 나머지 세계에 대해 폐쇄되는 것을 의미하지 않습니다. 그것은 당신이 누구에게 열려 있는지 선택하는 것을 의미합니다.


2
이 답변은 투표가 필요합니다! 다른 답변은 '규칙'을 다시 언급하지만이 답변 만이 규칙 뒤에있는 이유를 밝히고 요점을 정합니다.
mzoz

4
그러나 객체가 자신의 복사본을 제공하는 책임을지게하는 것이 더 낫지 않을까요? 그런 다음 객체의 딥 카피가 필요한 경우 동일한 클래스의 다른 객체 든 다른 클래스의 객체 o.deepCopy()든 상관 없습니다. 동일한 메커니즘 이든 상관 없습니다.
dirtside 2010 년

4

이것은 당신이 class Person클래스 에 있기 때문에 작동합니다 -클래스는 자신의 클래스 유형 내부를 찌를 수 있습니다. 이것은 복사 생성자를 작성할 때 정말 도움이됩니다. 예를 들면 다음과 같습니다.

class A
{
   private:
      int x;
      int y;
   public:
      A(int a, int b) x(a), y(b) {}
      A(A a) { x = a.x; y = y.x; }
};

아니면 작성하려는 경우 operator+operator-우리의 큰 숫자 클래스.


이것은 의존성 주입과 유사합니다. 개인 변수에 액세스 할 수없는 다른 클래스의 객체를 삽입 할 수도 있습니다.
Nageswaran

물론, 클래스 B의 객체에서 클래스 A를 구성하려고하는데 B에 개인 구성 요소가있는 경우 A는 친구로 선언되거나 공용 부분 만 볼 수 있습니다 (A가 B에서 파생 된 경우 보호 될 수 있음). ].
Mats Petersson 2013 년

Java와 .net에는 친구라는 개념이 없습니다. 그런 경우 어떻게 처리해야합니까?
Nageswaran 2013 년

1

Java에서 비공개 가시성의 의미가 객체 수준이 아닌 클래스 수준 인 이유에 대한 질문에 대해 2 센트 만하겠습니다.

여기서는 편리함 이 핵심 이라고 생각 합니다 . 사실, 객체 수준의 비공개 가시성은 OP에 의해 설명 된 시나리오에서 다른 클래스 (예 : 동일한 패키지)에 메소드를 노출해야했습니다.

사실 저는 클래스-개인 수준의 가시성 (예 : Java에서 제공)이 객체-개인 수준의 가시성과 비교할 때 문제를 생성한다는 것을 보여주는 예를 만들거나 찾을 수 없었습니다.

즉,보다 세분화 된 가시성 정책 시스템을 사용하는 프로그래밍 언어는 객체 수준과 클래스 수준에서 객체 가시성을 모두 제공 할 수 있습니다.

예를 들어 Eiffel 은 선택적 내보내기를 제공합니다. {NONE} (객체-비공개)에서 {ANY} (공용과 동일하며 기본값)에서 {PERSON}까지 모든 클래스 기능을 원하는 모든 클래스로 내보낼 수 있습니다. (class-private, OP의 예 참조), 특정 클래스 그룹 {PERSON, BANK}.

Eiffel에서 속성을 비공개로 만들고 다른 클래스가 그것에 할당되는 것을 막기 위해 getter를 작성할 필요가 없다는 점에 주목하는 것도 흥미 롭습니다. Eiffel의 공용 속성은 기본적으로 읽기 전용 모드에서 액세스 할 수 있으므로 값을 반환하기 위해 getter가 필요하지 않습니다.

물론 속성을 설정하려면 setter가 필요하지만 해당 속성에 대한 "할당 자"로 정의하여 숨길 수 있습니다. 이를 통해 원하는 경우 setter 호출 대신 더 편리한 할당 연산자를 사용할 수 있습니다.


0

때문에 private 액세스 한정자는 단지 내에서 그것을 볼 수 렌더링 클래스 . 이 메서드는 여전히 클래스에 있습니다.


내 질문은 왜 "클래스 내"처럼 디자인되었지만 "오직 객체 내에서만"이 아닌 이유입니다.
Nageswaran

그것이 자바가 만들어지는 방식이기 때문입니다.
darijan 2013-06-11

그리고 자바가 그렇게 만든 이유는 무엇입니까?
Nageswaran

자바는 성공하지 못했고 자바 제작자는 성공했습니다. 왜? 그들이 흔들기 때문에!
darijan 2014-07-11

Java 제작자는 이유 없이는이를 수행하지 않을 것이며이를 수행하는 데에는 몇 가지 이유가 있어야합니다. 나는 이유를 부탁 해요
Nageswaran

0

private필드는 필드가 선언 된 클래스 / 객체에 액세스 할 수 있습니다. 위치가 아닌 다른 클래스 / 객체에 대해 비공개입니다.


-1

여기서 가장 먼저 이해해야 할 것은 우리가해야 할 일은 oops 원칙을 따라야한다는 것입니다. 그래서 캡슐화는 데이터를 패키지 (즉, 클래스) 내에서 감싸고 모든 데이터를 Object로 표현하고 접근하기 쉽다는 것입니다. 따라서 필드를 개별적으로 액세스하는 것보다 비공개로 만들면. 그 결과 나쁜 기생충이 생깁니다.


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