2010-11-22 3 views
27
class TestClass 
{ 
    private string _privateString = "hello"; 
    void ChangeData() 
    { 
     TestClass otherTestClass = new TestClass(); 
     otherTestClass._privateString = "world"; 
    } 
} 

이 코드는 C# 및 PHP와 동등한 작업으로 컴파일되지만 누군가 otherTestClass._privateString을 여기서 바꿀 수있는 이유를 설명 할 수 있습니까?private 멤버 변수를 클래스 인스턴스별로 변경할 수있는 이유는 무엇입니까?

클래스의 인스턴스가 어떤 상황에서도 개인 멤버 변수를 변경할 수 없어야하고 otherTestClass._privateString에 액세스하려는 경우 '보호 수준으로 인해 액세스 할 수 없음'오류가 발생한다고 생각했을 것입니다.

그렇다고해서 개인 클래스에 개체를 인스턴스화하면 개인 멤버에 액세스 할 수 있습니까? 그리고 이것이 캡슐화를 어느 정도 깨뜨리지는 않을까요? 또는 나는 명백한 것을 놓치고 있는가?

  • (위 클래스의 디자인은 단지 뒤에 이론에 대해 궁금 좋은 방법입니다 있을지 물어 아니에요.)

편집 - 답변과 의견을 주셔서 감사합니다. 명확히하기 위해, 나는 이것을 수행 할 수 있는지 여부가 긍정적 인 특징으로 간주되는지 또는 대부분의 다른 언어가 그렇게하거나 다른 방식으로 수행하기 때문에 더 나은 컴파일 타임 검사/코드 명확성을 위해 필요한 절충안인지에 관심이 있습니다. 필자는 컴파일러가이 문제를 방지하거나 경고하지만, 언어 디자이너와는 거리가 멀다는 것이 이상적입니다. 이 방법으로 어떤 방법을 사용하면 어렵거나 불가능할 유용한 유용한 작업을 캡슐화를 위반하지 않고 수행 할 수 있습니다.

+0

BTW :'ChangeData()'를'static'으로 만들 수도 있습니다. 그러면 여전히 개인용 멤버에 액세스 할 수 있습니다. – ulrichb

+0

@ulrichb -'ChangeData()'가'static' 인 경우 private 멤버에 액세스하기 위해'this' 키워드를 사용할 수 없다는 OP에 유의해야합니다. – TheCloudlessSky

+1

Ruby에서 다른 언어의 예로서 public은 동일하지만 private은 "동일한 인스턴스에서만 액세스 가능"을 의미하며 protected는 "같은 클래스에서만 액세스 가능"을 의미합니다. 상속은 거기와 아무 상관이 없습니다. – Tesserex

답변

35

개인 멤버는 해당 클래스의 프로그램 텍스트 내의 모든 코드 (중첩 형식 포함)에서 액세스 할 수 있습니다. 그것은 당신이 다루고있는 클래스의 어떤 인스턴스와 관련이 없습니다.

이것은 캡슐화를 위반하지 않는다고 생각합니다. API는 여전히 구현과 분리되어 있지만 구현은보고있는 인스턴스에 관계없이 자체에 대해 "인식"합니다.

나는 다른 언어에서이 이 아니지만 액세스 가능성이 어떻게 작동하는지는 분명하지만 C# 및 Java에 대한 것입니다. (Java는 private 멤버에 액세스 할 수있는 것에 대해 약간 다른 규칙을 가지고 있지만 사용자가 작성한 코드는 여전히 작동합니다.)

+3

인스턴스 수준에서 액세스 가능성을 구현하려면 모든 멤버 변수 액세스에 대한 런타임 검사가 필요하지만이 모델은 컴파일 타임에 확인할 수 있습니다. –

+1

@James : 음, 꼭 그런 것은 아닙니다.비공개 멤버는 "this"참조를 통해서만 사용할 수 있습니다. 그것은 끔찍한 일이지만 가능한 일입니다. –

+1

Jon의 답변에이 유형의 액세스 제어를 사용하면 평등과 같은 n 개 연산자를 쉽게 작성할 수 있습니다. 어느 인스턴스도 다른 멤버에 액세스 할 수 없으면 동등 연산자를 구현하는 것이 훨씬 더 어려울 것입니다. –

9

이는 C#이 객체 수준 개인 정보 보호가 아닌 클래스 수준 개인 정보 보호를 시행하기 때문입니다.

대부분의 주류 언어는 동일한 정책 (예 : C#, C++ 및 Java)을 시행합니다. 그 이유는 다음과 같습니다 :

1) 개발자들이 그런 종류의 정책에 익숙하기 때문에 1)

2) 개체 수준의 개인 정보 보호는 매우 적은 장점으로 인해 너무 지루해질 수 있기 때문에 2).

+0

나는 거기에 있다고 믿지 않습니다. 컴파일러는 멤버 변수를 구별 할 수 있기 때문에 "this"를 사용할 필요가 있습니다. 예를 들어, 각 클래스의 멤버 값에 대한 getter 메서드가 필요하다는 지루한 생각이들 것입니다. 사실 캡슐화에 반대합니다. – Simone

+0

@ miket2e 복사체 생성자 또는 객체 레벨 프라이버시를 가진 간단한 Equals 함수를 구현해보십시오. 현재 C#에서는 간단합니다 : this._somePrivateField.Eq를 반환하십시오. uals (other._somePrivateField) - 당신이 other._somePrivateField에 접근 할 수 있다면 public getter를 추가하지 않고 그런 기능을 구현하는 방법은 무엇입니까? –

+1

@MichaelStum : 필드를 인스턴스가 개인 또는 인스턴스로 보호하는 이점 중 하나는 파생 클래스가 Liskov 대체 원칙을 위반하지 않고 해당 필드를 다시 사용할 수 있다는 것입니다. 그렇지 않으면, 그러한 re-purposing은 LSP 위반을 일으킬 수 있습니다. 'Equals'와 같은 것은 다른 객체의 내용을 받아들이는 클래스 - 프라이빗 'Equals' 메쏘드 (개별 매개 변수들의 묶음이나 클래스 - 보호 된 타입을 사용하는)를 구현함으로써 구현 될 수 있고, public '객체의 메소드는 그 상태를 다른 객체의'Protected' equals 메소드에 전달합니다. – supercat

관련 문제